最小费用最大流模板题
题意就是要找两条无交集的从1到n的路线,使距离和最小。
每条路只能走一次。
设置一个源,接到1点,设置一个汇,从n点接到汇。
为保证无交集,我们把每条边的流量设置为1,而源发出的流量和汇接收的流量均为2。每条边的费用就是该边在原图中的权值。
1 #include <cstdio> 2 #include <iostream> 3 #include <string.h> 4 #include <queue> 5 using namespace std; 6 const int N=1050; 7 const int M=10050; 8 struct{ 9 int v, cap, cost, next, re;//re 逆边的下标 10 }e[M]; 11 int n,m,ans,k; 12 int first[N],pre[N],dis[N]; 13 void init(){ 14 k=0; 15 memset(first,-1,sizeof(first)); 16 ans=0; 17 } 18 void addedge(int u,int v,int ca,int co){ 19 e[k].v=v; 20 e[k].cap=ca; 21 e[k].cost=co; 22 e[k].next=first[u]; 23 e[k].re=k+1; 24 first[u]=k++; 25 e[k].v=u; 26 e[k].cap=0; 27 e[k].cost=-co; 28 e[k].next=first[v]; 29 e[k].re=k-1; 30 first[v]=k++; 31 } 32 bool spfa(int s,int t){ 33 memset(dis,0x3f,sizeof(dis)); 34 queue<int >q; 35 int inq[N]={0}; 36 q.push(s); 37 inq[s]=1; 38 dis[0]=0; 39 while(!q.empty()){ 40 int u=q.front(); 41 q.pop(); 42 for(int i=first[u];i!=-1;i=e[i].next){ 43 int v=e[i].v; 44 if(e[i].cap&&dis[v]>dis[u]+e[i].cost){ 45 46 dis[v]=dis[u]+e[i].cost; 47 pre[v]=i; 48 if(!inq[v]){ 49 inq[v]=1; 50 q.push(v); 51 } 52 } 53 } 54 inq[u]=0; 55 } 56 if(dis[t]==0x3f3f3f3f){return false;} 57 return true; 58 } 59 void solve(){ 60 int u, p, sum = 1<<30; 61 for(u = n; u != 0; u = e[e[p].re].v){ 62 p = pre[u]; 63 sum = min(sum, e[p].cap); 64 } 65 for(u = n; u != 0; u = e[e[p].re].v){ 66 p = pre[u]; 67 e[p].cap -= sum; 68 e[e[p].re].cap += sum; 69 ans += sum * e[p].cost; 70 } 71 } 72 int main(){ 73 int u,v,c; 74 init(); 75 scanf("%d%d",&n,&m); 76 while(m--){ 77 scanf("%d%d%d",&u,&v,&c); 78 addedge(u,v,1,c); 79 addedge(v,u,1,c); 80 } 81 addedge(0,1,2,0); 82 addedge(n,n+1,2,0); 83 84 n++; 85 while(spfa(0,n)){solve();} 86 printf("%d\n",ans); 87 return 0; 88 }
时间: 2024-10-11 00:06:15