【uva 1658】Admiral(图论--网络流 最小费用最大流)
题意:有个N个点M个边的有向加权图,求1~N的两条不相交路径(除了起点和终点外没有公共点),使得权和最小。
解法:不相交?也就是一个点只能经过一次,也就是我后面博文会讲的“结点容量问题”。(呃不,写完这博文几天后的今天,我负责任地 m(._.)m 告诉大家,我不会写这博文了......我的时间不多了...... m(_ _;;m 大家可以看蓝书。)常用方法就是拆点法,把一个点拆成两个点,中间连一条容量为1、费用为0的边。于是求1到 n 的流量为2的最小费用流就可以了。
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<queue> 6 using namespace std; 7 8 const int N=1010,M=10010,NN=2010,MM=22000,D=110,INF=(int)1e9; 9 int n,m,len; 10 int last[NN],d[NN],vis[NN],flow[NN]; 11 int pre[NN],id[NN]; 12 struct edge{int x,y,fl,c,next;}e[MM]; 13 queue<int> q; 14 15 int mmin(int x,int y) {return x<y?x:y;} 16 void ins(int x,int y,int fl,int c) 17 { 18 e[++len].x=x,e[len].y=y,e[len].fl=fl,e[len].c=c; 19 e[len].next=last[x],last[x]=len; 20 e[++len].x=y,e[len].y=x,e[len].fl=0,e[len].c=-c; 21 e[len].next=last[y],last[y]=len; 22 } 23 bool spfa(int st,int ed) 24 { 25 while (!q.empty()) q.pop(); 26 memset(d,63,sizeof(d));//>1e9 27 memset(vis,0,sizeof(vis)); 28 memset(pre,0,sizeof(pre)); 29 q.push(st); 30 d[st]=0,vis[st]=1,flow[st]=INF; 31 while (!q.empty()) 32 { 33 int x=q.front(); q.pop(); 34 vis[x]=0;//spfa 35 for (int i=last[x];i;i=e[i].next) 36 { 37 int y=e[i].y; 38 if (d[x]+e[i].c<d[y] && e[i].fl) 39 { 40 d[y]=d[x]+e[i].c; 41 flow[y]=mmin(flow[x],e[i].fl); 42 pre[y]=x, id[y]=i; 43 if (!vis[y]) q.push(y),vis[y]=1; 44 } 45 } 46 } 47 return pre[ed]; 48 } 49 int Max_flow(int st,int ed) 50 { 51 int sum=0; 52 while (spfa(st,ed)) 53 { 54 sum+=flow[ed]*d[ed]; 55 for (int i=ed;i!=st;i=pre[i]) 56 { 57 e[id[i]].fl-=flow[ed]; 58 e[id[i]^1].fl+=flow[ed]; 59 } 60 } 61 return sum; 62 } 63 int main() 64 { 65 while (scanf("%d%d",&n,&m)!=EOF) 66 { 67 int x,y,z; len=1; 68 memset(last,0,sizeof(last)); 69 for (int i=2;i<n;i++) ins(i,n+i-1,1,0); 70 ins(n,2*n-1,2,0); 71 //拆点就是真的拆点不能ins(i,i...) n+1~2n-2 72 for (int i=1;i<=m;i++) 73 { 74 scanf("%d%d%d",&x,&y,&z); 75 if (x!=1) x=n+x-1;//只有1没有拆多一个点 76 ins(x,y,1,z); 77 } 78 //for (int i=2;i<=len;i++) 79 // printf("%d %d %d %d %d\n",e[i].x,e[i].y,e[i].fl,e[i].c,e[i].next); 80 int ans=Max_flow(1,2*n-1); 81 printf("%d\n",ans); 82 } 83 return 0; 84 }