一个最小费用最大流的简单建模题;
比赛的时候和小珺合力想到了这个题目的模型;
方法:拆点+边的容量为1
这样就可以保证他们不会在点上和边上相遇了!
感谢刘汝佳大神的模板,让我这个网络流的小白A了这个题。
代码:
1 #include<cstdio> 2 #include<cstring> 3 #include<vector> 4 #include<queue> 5 #define maxn 42005 6 #define inf 99999 7 using namespace std; 8 9 struct edge 10 { 11 int from ,to,cap,flow,cost; 12 }; 13 14 struct mcmf 15 { 16 int n,m,s,t; 17 vector<edge>edges; 18 vector<int>g[maxn]; 19 int inq[maxn],d[maxn],p[maxn],a[maxn]; 20 void init(int n) 21 { 22 this->n=n; 23 edges.clear(); 24 for(int i=0; i<n; i++)g[i].clear(); 25 } 26 void addedge(int from,int to,int cap,int cost) 27 { 28 edges.push_back((edge){from,to,cap,0,cost}); 29 edges.push_back((edge){to,from,0,0,-cost}); 30 m=edges.size(); 31 g[from].push_back(m-2); 32 g[to].push_back(m-1); 33 } 34 bool bellmamford(int s,int t,int &flow,int& cost) 35 { 36 for(int i=0; i<n; i++)d[i]=inf; 37 memset(inq,0,sizeof inq); 38 d[s]=0; 39 inq[s]=1; 40 p[s]=0; 41 a[s]=inf; 42 queue<int>q; 43 q.push(s); 44 while(!q.empty()) 45 { 46 int u=q.front(); 47 q.pop(); 48 inq[u]=0; 49 for(int i=0; i<g[u].size(); i++) 50 { 51 edge& e=edges[g[u][i]]; 52 if(e.cap>e.flow&&d[e.to]>d[u]+e.cost) 53 { 54 d[e.to]=d[u]+e.cost; 55 p[e.to]=g[u][i]; 56 a[e.to]=min(a[u],e.cap-e.flow); 57 if(!inq[e.to]) 58 { 59 q.push(e.to); 60 inq[e.to]=1; 61 } 62 } 63 } 64 } 65 if(d[t]==inf)return false; 66 flow+=a[t]; 67 cost+=d[t]*a[t]; 68 int u=t; 69 while(u!=s) 70 { 71 edges[p[u]].flow+=a[t]; 72 edges[p[u]^1].flow-=a[t]; 73 u=edges[p[u]].from; 74 } 75 return true; 76 } 77 78 int mincost(int s,int t) 79 { 80 int flow=0,cost=0; 81 while(bellmamford(s,t,flow,cost)); 82 return cost; 83 } 84 }getans; 85 86 int main() 87 { 88 int nn,mm,f,t,c; 89 while(scanf("%d%d",&nn,&mm)!=EOF) 90 { 91 getans.init(2*nn+2); 92 getans.addedge(0,1+nn,2,0); 93 getans.addedge(nn,2*nn+1,2,0); 94 for(int i=2;i<nn;i++) 95 getans.addedge(i,i+nn,1,0); 96 for(int i=0; i<mm; i++) 97 { 98 scanf("%d%d%d",&f,&t,&c); 99 getans.addedge(f+nn,t,1,c); 100 } 101 printf("%d ",getans.mincost(0,2*nn+1)); 102 } 103 return 0; 104 }