【网络流24题】No.11(航空路线问题 最长不相交路径 最大费用流)
【题意】
给定一张航空图, 图中顶点代表城市, 边代表 2 城市间的直通航线。 现要求找出一条满足下述限制条件的且途经城市最多的旅行路线。
(1) 从最西端城市出发,单向从西向东途经若干城市到达最东端城市,然后再单向从东向西飞回起点(可途经若干城市) 。
(2) 除起点城市外, 任何城市只能访问 1 次。
输入文件示例
input.txt
8 9
Vancouver
Yellowknife
Edmonton
Calgary
Winnipeg
Toronto
Montreal
Halifax
Vancouver Edmonton
Vancouver Calgary
Calgary Winnipeg
Winnipeg Toronto
Toronto Halifax
Montreal Halifax
Edmonton Montreal
Edmonton Yellowknife
Edmonton Calgary输出文件示例
output.txt
7
Vancouver
Edmonton
Montreal
Halifax
Toronto
Winnipeg
Calgary
Vancouver
【分析】
只有我这种智障才会想半天 保证 从西向东怎么破吧。。
都知道是怎么做的了。。。
这种回路其实相当于从起点到终点走两次 然后路径不相交。
不相交这一点约束了我们不能把两次路径分开做的。。
点只能走一遍,拆点,流量为1,费用为1.
然后按照原图也建边。(只能从西往东走,双向边事实上只建一条)
1 #include<cstdio> 2 #include<cstdlib> 3 #include<cstring> 4 #include<iostream> 5 #include<algorithm> 6 #include<queue> 7 #include<cmath> 8 #include<map> 9 using namespace std; 10 #define Maxn 2010 11 #define INF 0xfffffff 12 13 map<string,int> M; 14 int n,m; 15 16 struct node 17 { 18 int x,y,f,o,c,next; 19 }t[Maxn*1010];int len; 20 int first[Maxn]; 21 22 int mymin(int x,int y) {return x<y?x:y;} 23 int mymax(int x,int y) {return x>y?x:y;} 24 25 void ins(int x,int y,int f,int c) 26 { 27 t[++len].x=x;t[len].y=y;t[len].f=f;t[len].c=c; 28 t[len].next=first[x];first[x]=len;t[len].o=len+1; 29 t[++len].x=y;t[len].y=x;t[len].f=0;t[len].c=-c; 30 t[len].next=first[y];first[y]=len;t[len].o=len-1; 31 } 32 33 int st,ed; 34 queue<int > q; 35 int dis[Maxn],pre[Maxn],flow[Maxn]; 36 bool inq[Maxn]; 37 bool bfs() 38 { 39 while(!q.empty()) q.pop(); 40 memset(dis,-1,sizeof(dis)); 41 memset(inq,0,sizeof(inq)); 42 q.push(st);dis[st]=0;flow[st]=INF;inq[st]=1; 43 while(!q.empty()) 44 { 45 int x=q.front(); 46 for(int i=first[x];i;i=t[i].next) if(t[i].f>0) 47 { 48 int y=t[i].y; 49 if(dis[y]<dis[x]+t[i].c) 50 { 51 dis[y]=dis[x]+t[i].c; 52 pre[y]=i; 53 flow[y]=mymin(flow[x],t[i].f); 54 if(!inq[y]) 55 { 56 inq[y]=1; 57 q.push(y); 58 } 59 } 60 } 61 inq[x]=0;q.pop(); 62 } 63 if(dis[ed]==-1) return 0; 64 return 1; 65 } 66 67 void output() 68 { 69 for(int i=1;i<=len;i+=2) 70 printf("%d->%d %d %d\n",t[i].x,t[i].y,t[i].f,t[i].c); 71 printf("\n"); 72 } 73 74 void max_flow() 75 { 76 int ans=0,sum=0; 77 while(bfs()) 78 { 79 sum+=dis[ed]*flow[ed]; 80 ans+=flow[ed]; 81 int now=ed; 82 while(now!=st) 83 { 84 t[pre[now]].f-=flow[ed]; 85 t[t[pre[now]].o].f+=flow[ed]; 86 now=t[pre[now]].x; 87 } 88 } 89 if(ans<2) printf("No Solution!\n"); 90 else 91 { 92 printf("%d\n",sum-2); 93 } 94 } 95 96 string s[Maxn],ss; 97 bool vis[Maxn*Maxn]; 98 void dfs(int x,bool qq) 99 { 100 if(x==n) return; 101 if(x<n) 102 { 103 if(qq) cout<<s[x]<<endl; 104 dfs(x+n,qq); 105 if(!qq) cout<<s[x]<<endl; 106 return; 107 } 108 for(int i=first[x];i;i=t[i].next) if(t[i].f==0&&!vis[i]) 109 { 110 vis[i]=1; 111 dfs(t[i].y,qq); 112 return; 113 } 114 } 115 116 void init() 117 { 118 scanf("%d%d",&n,&m); 119 for(int i=1;i<=n;i++) 120 { 121 cin>>s[i]; 122 M[s[i]]=i; 123 } 124 for(int i=1;i<=m;i++) 125 { 126 int x,y,tt; 127 cin>>ss; 128 x=M[ss]; 129 cin>>ss; 130 y=M[ss]; 131 if(x==1&&y==n) ins(x+n,y,2,0); 132 else ins(x+n,y,1,0); 133 } 134 st=1;ed=n+n; 135 ins(1,1+n,2,1);ins(n,n+n,2,1); 136 for(int i=2;i<n;i++) ins(i,i+n,1,1); 137 memset(vis,0,sizeof(vis)); 138 } 139 140 int main() 141 { 142 init(); 143 max_flow(); 144 dfs(1,1); 145 cout<<s[n]<<endl; 146 dfs(1,0); 147 return 0; 148 }
有没有SBJ ,桑心。。。
本机测的最长路径长度是对的,方案懒得看了,应该没什么问题吧。。
2016-11-04 19:39:24