编程开发晨跑 费用流问题求解
题目大意:给一有向图G,多次从1到n,最大化经过点数,最小化边权和
把每个点拆成入和出,将除1,n的所有点入向出连一条容量为1,费用为0的边
1和n的连INF(不限制经过次数)
超级源连1的入,n的出连汇,容量都是INF,费用为0
对于每条边(u,v,k),从u的出到v的入连一条容量为1费用为k的边
跑最小费用最大流
代码如下:
#include#include #include #define N 505 #define INF 2147483647 using namespace std; const int S=501; const int T=502; queue q; int n,m,x,y,k,ans,cost,top=1; int d[N],fir[N]; bool b[N]; inline int read(){ int x=0,f=1;char c; do c=getchar(),f=c=='-'?-1:f; while(!isdigit(c)); do x=(x<<3)+(x<<1)+c-'0',c=getchar(); while(isdigit(c)); return x*f; } struct Edge{ int to,nex,k,v; Edge(int _=0,int __=0,int ___=0,int ____=0):to(_),nex(__),k(___),v(____){} }nex[40020]; inline void add(int x,int y,int k,int v){ nex[++top]=Edge(y,fir[x],k,v); fir[x]=top; } inline bool spfa(){ for(int i=1;i<=502;i++) d[i]=INF,b[i]=false; d[S]=0;q.push(S); while(!q.empty()){ int x=q.front();q.pop(); b[x]=false; for(int i=fir[x];i;i=nex[i].nex) if(nex[i].k && d[nex[i].to]>d[x]+nex[i].v){ d[nex[i].to]=d[x]+nex[i].v; if(!b[nex[i].to]) q.push(nex[i].to),b[nex[i].to]=true; } } return d[T]!=INF; } int dfs(int x,int v){ if(!v || x==T){ cost+=v*d[T]; return v; } int tmp=0; b[x]=true; for(int i=fir[x];i;i=nex[i].nex) if(!b[nex[i].to] && nex[i].k && d[nex[i].to]==d[x]+nex[i].v){ int f=dfs(nex[i].to,min(v,nex[i].k)); v-=f;nex[i].k-=f;nex[i^1].k+=f;tmp+=f; if(!v) break; } if(!tmp) d[x]=-1; return tmp; } inline void Dinic(){ while(spfa()) ans+=dfs(S,INF); } int main(){ n=read();m=read(); for(int i=2;i