题意:
给出n个点,m条边,问一个人从家走到barn的最短长度(设家1,barn为N);
所以,问的就是 去:1->N 和 返:N->1 两条路径的最短长度,两条路径不能重复;
所以,问题变成了:有两个人,从1->N,它们所走路径不能重复(走的边不能重复),求最短长度。
所以变成了最小费用最大流问题,自己再自己想想。
思路:
我以为是个最短路。。但是最短路貌似好像不能解决路径重复问题叭。。
妥妥的模板,我终于碰到了,原来我先做的都是变形题,我太难了。。
题意转化到算法上还是比较不好想到,怎么分析在上面的题意里面已经写清楚了。
容量cap传入的为1或者2(自己判断传入什么),花费cost即点和点之间的权值。
建边最重要:
scanf("%d %d",&n,&m); tot=0,s=0,t=n+1; memset(head,-1,sizeof(head)); for(int i=1; i<=m; i++) { int u,v,w; scanf("%d %d %d",&u,&v,&w); add(u,v,1,w);//cap,cost add(v,u,1,w); } add(s,1,2,0); add(n,t,2,0);
邻接表建边:
1 void add(int u,int v,int cap,int cost) 2 { 3 e[tot].to=v; 4 e[tot].nextt=head[u]; 5 e[tot].cap=cap; 6 e[tot].cost=cost; 7 e[tot].flow=0; 8 head[u]=tot++; 9 10 e[tot].to=u; 11 e[tot].nextt=head[v]; 12 e[tot].cap=0; 13 e[tot].cost=-cost; 14 e[tot].flow=0; 15 head[v]=tot++; 16 17 }
SPFA:
1 bool SPFA() 2 { 3 for(int i=0; i<=t; i++) 4 { 5 dist[i]=inf; 6 book[i]=0; 7 pre[i]=-1;//head不能放在这里i清,否则为0 8 } 9 book[s]=1; 10 dist[s]=0; 11 queue<int>Q; 12 Q.push(s); 13 while(!Q.empty()) 14 { 15 int u=Q.front(); 16 Q.pop(); 17 book[u]=0; 18 for(int i=head[u]; i!=-1; i=e[i].nextt) 19 { 20 int v=e[i].to; 21 if(e[i].cap>e[i].flow&&dist[v]>dist[u]+e[i].cost) 22 { 23 dist[v]=dist[u]+e[i].cost; 24 pre[v]=i; 25 if(book[v]==0) 26 { 27 book[v]=1; 28 Q.push(v); 29 } 30 } 31 } 32 } 33 if(dist[t]!=inf) 34 return 1; 35 return 0; 36 }
MCMF:
1 int MCMF() 2 { 3 int flow=0,cost=0; 4 while(SPFA()) 5 { 6 int minn=inf; 7 for(int i=pre[t]; i!=-1; i=pre[e[i^1].to]) 8 minn=min(minn,e[i].cap-e[i].flow); 9 for(int i=pre[t]; i!=-1; i=pre[e[i^1].to]) 10 { 11 e[i].flow+=minn; 12 e[i^1].flow-=minn; 13 cost+=e[i].cost*minn; 14 } 15 flow+=minn; 16 } 17 return cost; 18 }
AC代码:
1 #include<stdio.h> 2 #include<iostream> 3 #include<queue> 4 #include<string.h> 5 using namespace std; 6 #define inf 0x3f3f3f3f 7 8 const int N=1010; 9 bool book[N]; 10 int n,m,tot,s,t,pre[10*N],head[10*N],dist[10*N]; 11 struct node 12 { 13 int to,nextt,cap,flow,cost; 14 } e[N*N]; 15 16 void add(int u,int v,int cap,int cost) 17 { 18 e[tot].to=v; 19 e[tot].nextt=head[u]; 20 e[tot].cap=cap; 21 e[tot].cost=cost; 22 e[tot].flow=0; 23 head[u]=tot++; 24 25 e[tot].to=u; 26 e[tot].nextt=head[v]; 27 e[tot].cap=0; 28 e[tot].cost=-cost; 29 e[tot].flow=0; 30 head[v]=tot++; 31 32 } 33 34 bool SPFA() 35 { 36 for(int i=0; i<=t; i++) 37 { 38 dist[i]=inf; 39 book[i]=0; 40 pre[i]=-1;//head不能放在这里i清,否则为0 41 } 42 book[s]=1; 43 dist[s]=0; 44 queue<int>Q; 45 Q.push(s); 46 while(!Q.empty()) 47 { 48 int u=Q.front(); 49 Q.pop(); 50 book[u]=0; 51 for(int i=head[u]; i!=-1; i=e[i].nextt) 52 { 53 int v=e[i].to; 54 if(e[i].cap>e[i].flow&&dist[v]>dist[u]+e[i].cost) 55 { 56 dist[v]=dist[u]+e[i].cost; 57 pre[v]=i; 58 if(book[v]==0) 59 { 60 book[v]=1; 61 Q.push(v); 62 } 63 } 64 } 65 } 66 if(dist[t]!=inf) 67 return 1; 68 return 0; 69 } 70 71 int MCMF() 72 { 73 int flow=0,cost=0; 74 while(SPFA()) 75 { 76 int minn=inf; 77 for(int i=pre[t]; i!=-1; i=pre[e[i^1].to]) 78 minn=min(minn,e[i].cap-e[i].flow); 79 for(int i=pre[t]; i!=-1; i=pre[e[i^1].to]) 80 { 81 e[i].flow+=minn; 82 e[i^1].flow-=minn; 83 cost+=e[i].cost*minn; 84 } 85 flow+=minn; 86 } 87 return cost; 88 } 89 90 int main() 91 { 92 scanf("%d %d",&n,&m); 93 tot=0,s=0,t=n+1; 94 memset(head,-1,sizeof(head)); 95 for(int i=1; i<=m; i++) 96 { 97 int u,v,w; 98 scanf("%d %d %d",&u,&v,&w); 99 add(u,v,1,w);//cap,cost 100 add(v,u,1,w); 101 } 102 add(s,1,2,0); 103 add(n,t,2,0); 104 int ans=MCMF(); 105 printf("%d\n",ans); 106 return 0; 107 }