[网络流24题] 航空路线问题 (费用流)
这道题的图还挺好想的吧
反正都是无向边,起点走到终点再回到起点,就相当于从起点走$2$次到达终点,且这两次不经过相同的点,还要经过尽可能多的点
很经典的费用流建图
限制点通过次数->拆点连边,流量为$1$,费用为$1$
图中的其他边,编号较小的指向编号较大的,流量为$inf$,费用为$0$
跑最大费用最大流即可
注意有$1$直接到$n$的情况,所以其他边流量要设置到至少大于$2$
至于输出方案呢,在残量网络中,每次都$dfs$找出一条从汇点到源点的路径即可
1 #include <map> 2 #include <string> 3 #include <cstdio> 4 #include <cstring> 5 #include <iostream> 6 #include <algorithm> 7 #define N1 210 8 #define M1 40010 9 #define ll long long 10 #define dd double 11 #define inf 0x3f3f3f3f 12 using namespace std; 13 14 int gint() 15 { 16 int ret=0,fh=1;char c=getchar(); 17 while(c<'0'||c>'9'){if(c=='-')fh=-1;c=getchar();} 18 while(c>='0'&&c<='9'){ret=ret*10+c-'0';c=getchar();} 19 return ret*fh; 20 } 21 struct Edge{ 22 int head[N1],to[M1<<1],nxt[M1<<1],flow[M1<<1],cost[M1<<1],cte; 23 void ae(int u,int v,int F,int C) 24 { 25 cte++; to[cte]=v; flow[cte]=F; cost[cte]=C; 26 nxt[cte]=head[u]; head[u]=cte; 27 } 28 }e,E; 29 int n,m,nn,S,T; 30 map<string,int>mp; 31 int que[M1],hd,tl,cost[N1],flow[N1],id[N1],use[N1]; 32 int spfa() 33 { 34 int x,j,v; 35 memset(flow,0,sizeof(flow)); 36 for(j=S;j<=T;j++) cost[j]=-inf; 37 hd=1,tl=0; que[++tl]=S; cost[S]=0; flow[S]=inf; use[S]=1; 38 while(hd<=tl) 39 { 40 x=que[hd++]; 41 for(j=e.head[x];j;j=e.nxt[j]) 42 { 43 v=e.to[j]; 44 if( cost[v]<cost[x]+e.cost[j] && e.flow[j]>0 ) 45 { 46 cost[v]=cost[x]+e.cost[j]; id[v]=j; 47 flow[v]=min(flow[x],e.flow[j]); 48 if(!use[v]) que[++tl]=v, use[v]=1; 49 } 50 } 51 use[x]=0; 52 } 53 return cost[T]!=-inf; 54 } 55 int stk[N1],tp; 56 void dfs(int x) 57 { 58 int j,v; 59 if(x<=n) stk[++tp]=x; 60 if(x==1) return; 61 for(j=e.head[x];j;j=e.nxt[j]) 62 { 63 v=e.to[j]; 64 if(!e.flow[j]) continue; 65 if(x>n){ 66 if(v==x-n) 67 { e.flow[j]--; dfs(v); break; } 68 }else{ 69 if(v<x+n) 70 { e.flow[j]--; dfs(v); break; } 71 } 72 } 73 } 74 char str[N1][20]; 75 void EK() 76 { 77 int x,tcost=0,mxflow=0,i,len,j; 78 while(spfa()) 79 { 80 mxflow+=flow[T]; tcost+=flow[T]*cost[T]; 81 for(x=T;x!=S;x=e.to[id[x]^1]) 82 { 83 e.flow[id[x]]-=flow[T]; 84 e.flow[id[x]^1]+=flow[T]; 85 } 86 } 87 if(mxflow<2){ puts("No Solution!"); return; } 88 printf("%d\n",tcost-2); 89 dfs(nn); 90 while(tp) 91 { 92 x=stk[tp]; len=strlen(str[x]); 93 for(j=0;j<len;j++) printf("%c",str[x][j]); 94 puts(""); tp--; 95 } 96 dfs(nn); 97 for(i=2;i<=tp;i++) 98 { 99 x=stk[i]; len=strlen(str[x]); 100 for(j=0;j<len;j++) printf("%c",str[x][j]); 101 puts(""); 102 } 103 } 104 int main() 105 { 106 scanf("%d%d",&n,&m); 107 string s;int i,j,x,y,len; 108 nn=n+n; S=0; T=nn+1; e.cte=1; 109 for(i=1;i<=n;i++) 110 { 111 cin>>s; mp[s]=i; len=s.length(); 112 for(j=0;j<len;j++) 113 str[i][j]=s[j]; 114 } 115 e.ae(1,1+n,2,1); e.ae(1+n,1,0,-1); 116 e.ae(n,n+n,2,1); e.ae(n+n,n,0,-1); 117 for(i=2;i<n;i++) e.ae(i,i+n,1,1), e.ae(i+n,i,0,-1); 118 for(i=1;i<=m;i++) 119 { 120 cin>>s; x=mp[s]; cin>>s; y=mp[s]; 121 if(x>y) swap(x,y); 122 e.ae(x+n,y,2,0); e.ae(y,x+n,0,0); 123 } 124 e.ae(S,1,2,0); e.ae(1,S,0,0); 125 e.ae(nn,T,2,0); e.ae(T,nn,0,0); 126 EK(); 127 return 0; 128 }