【PowerOJ1746&网络流24题】航空路线问题(费用流)

题意:

 

 思路:

【问题分析】

求最长两条不相交路径,用最大费用最大流解决。

【建模方法】

把第i个城市拆分成两个顶点<i.a>,<i.b>。

1、对于每个城市i,连接(<i.a>,<i.b>)一条容量为1,费用为1的有向边,特殊地(<1.a>,<1.b>)和(<N.a>,<N.b>)容量设为2。

2、如果城市i,j(j>i)之间有航线,从<i.b>到<j.a>连接一条容量为1,费用为0的有向边。

求源<1.a>到汇<N.b>的最大费用最大流。如果(<1.a>,<1.b>)不是满流,那么无解。否则存在解,即为最大费用最大流量 - 2。

【建模分析】

每条航线都是自西向东,本题可以转化为求航线图中从1到N两条不相交的路径,使得路径长度之和最大。转化为网络流模型,就是找两条最长的增广路。由于每个城市只能访问一次,要把城市拆成两个

点,之间连接一条容量为1的边,费用设为1。因为要找两条路径,所以起始点和终点内部的边容量要设为2。那么费用流值-2就是两条路径长度之和,为什么减2,因为有两条容量为2的边多算了1的费用。

求最大费用最大流后,如果(<1.a>,<1.b>)不是满流,那么我们找到的路径不够2条(可能是1条,也可能0条),所以无解。

【问题另解】

经典的多线程动态规划问题。

  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 typedef long long ll;
  4 typedef unsigned int uint;
  5 typedef unsigned long long ull;
  6 typedef long double ld;
  7 typedef pair<int,int> PII;
  8 typedef pair<ll,ll> Pll;
  9 typedef vector<int> VI;
 10 typedef vector<PII> VII;
 11 typedef pair<ll,ll>P;
 12 #define N  100010
 13 #define M  1000000
 14 #define INF 1e9
 15 #define fi first
 16 #define se second
 17 #define MP make_pair
 18 #define pb push_back
 19 #define pi acos(-1)
 20 #define mem(a,b) memset(a,b,sizeof(a))
 21 #define rep(i,a,b) for(int i=(int)a;i<=(int)b;i++)
 22 #define per(i,a,b) for(int i=(int)a;i>=(int)b;i--)
 23 #define lowbit(x) x&(-x)
 24 #define Rand (rand()*(1<<16)+rand())
 25 #define id(x) ((x)<=B?(x):m-n/(x)+1)
 26 #define ls p<<1
 27 #define rs p<<1|1
 28 
 29 const ll MOD=1e9+7,inv2=(MOD+1)/2;
 30       double eps=1e-6;
 31       int dx[4]={-1,1,0,0};
 32       int dy[4]={0,0,-1,1};
 33 
 34 int head[N],vet[N],len1[N],len2[N],nxt[N],dis[N],q[N],inq[N],L[N],a[N],b[N],
 35     num[N][2],pre[N][2],s,S,T,tot,ans1,ans2;
 36 
 37 char ch[N][20],s1[20],s2[20];
 38 
 39 int read()
 40 {
 41    int v=0,f=1;
 42    char c=getchar();
 43    while(c<48||57<c) {if(c=='-') f=-1; c=getchar();}
 44    while(48<=c&&c<=57) v=(v<<3)+v+v+c-48,c=getchar();
 45    return v*f;
 46 }
 47 
 48 void add(int a,int b,int c,int d)
 49 {
 50     nxt[++tot]=head[a];
 51     vet[tot]=b;
 52     len1[tot]=c;
 53     len2[tot]=d;
 54     head[a]=tot;
 55 
 56     nxt[++tot]=head[b];
 57     vet[tot]=a;
 58     len1[tot]=0;
 59     len2[tot]=-d;
 60     head[b]=tot;
 61 }
 62 
 63 bool spfa()
 64 {
 65     rep(i,1,s)
 66     {
 67         dis[i]=-INF;
 68         inq[i]=0;
 69     }
 70     int t=0,w=1;
 71     q[1]=S; dis[S]=0; inq[S]=1;
 72     while(t<w)
 73     {
 74         t++; int u=q[t%(s+5)]; inq[u]=0;
 75         int e=head[u];
 76         while(e)
 77         {
 78             int v=vet[e];
 79             if(len1[e]&&dis[u]+len2[e]>dis[v])
 80             {
 81                 dis[v]=dis[u]+len2[e];
 82                 pre[v][0]=u;
 83                 pre[v][1]=e;
 84                 if(!inq[v])
 85                 {
 86                     w++; q[w%(s+5)]=v; inq[v]=1;
 87                 }
 88             }
 89             e=nxt[e];
 90         }
 91     }
 92     if(dis[T]==-INF) return 0;
 93     return 1;
 94 }
 95 
 96 void mcf()
 97 {
 98     int k=T;
 99     int t=INF;
100     while(k!=S)
101     {
102         int e=pre[k][1];
103         t=min(t,len1[e]);
104         k=pre[k][0];
105     }
106     ans1+=t;
107     k=T;
108     while(k!=S)
109     {
110         int e=pre[k][1];
111         len1[e]-=t;
112         len1[e^1]+=t;
113         ans2+=t*len2[e];
114         k=pre[k][0];
115     }
116 }
117 
118 void print(int k)
119 {
120     rep(i,1,L[k]) printf("%c",ch[k][i]);
121     printf("\n");
122 }
123 
124 int main()
125 {
126     //freopen("1.in","r",stdin);
127     int n=read(),m=read();
128     rep(i,1,n)
129     {
130         scanf("%s",ch[i]+1);
131         L[i]=strlen(ch[i]+1);
132     }
133     s=0;
134     rep(i,1,n)
135      rep(j,0,1) num[i][j]=++s;
136     S=num[1][0],T=num[n][1];
137     tot=1;
138     add(num[1][0],num[1][1],2,1);
139     rep(i,2,n-1) add(num[i][0],num[i][1],1,1);
140     add(num[n][0],num[n][1],2,1);
141 
142     int p=0;
143     rep(i,1,m)
144     {
145         scanf("%s",s1+1);
146         scanf("%s",s2+1);
147         int L1=strlen(s1+1),L2=strlen(s2+1),id1=0,id2=0;
148         rep(j,1,n)
149         {
150             if(L[j]!=L1) continue;
151             int flag=1;
152             rep(k,1,L1)
153              if(ch[j][k]!=s1[k]){flag=0; break;}
154             if(flag){id1=j; break;}
155         }
156 
157         rep(j,1,n)
158         {
159             if(L[j]!=L2) continue;
160             int flag=1;
161             rep(k,1,L2)
162              if(ch[j][k]!=s2[k]){flag=0; break;}
163             if(flag){id2=j; break;}
164         }
165 
166         if(id1>id2) swap(id1,id2);
167         if(id1==1&&id2==n) p=1;
168         add(num[id1][1],num[id2][0],1,0);
169     }
170     ans1=0,ans2=0;
171     while(spfa()) mcf();
172     //printf("ans1=%d ans2=%d\n",ans1,ans2);
173     if(ans1==1&&p)
174     {
175         printf("2\n");
176         print(1);
177         print(n);
178         print(1);
179     }
180 
181      else if(ans1<2) printf("No Solution!\n");
182       else
183       {
184          printf("%d\n",ans2-2);
185          int k=1,m1=0,m2=0;
186          while(k!=n)
187          {
188              a[++m1]=k;
189              int u=num[k][1],e=head[u];
190              while(e)
191              {
192                  int v=vet[e];
193                  if(!len1[e])
194                  {
195                      k=(v+1)/2; len1[e]=-1;
196                      break;
197                  }
198                  e=nxt[e];
199              }
200 
201          }
202          k=1;
203          while(k!=n)
204          {
205              b[++m2]=k;
206              int u=num[k][1],e=head[u];
207              while(e)
208              {
209                  int v=vet[e];
210                  if(!len1[e])
211                  {
212                      k=(v+1)/2; len1[e]=-1;
213                      break;
214                  }
215                  e=nxt[e];
216              }
217          }
218          b[++m2]=n;
219          rep(i,1,m2) print(b[i]);
220          per(i,m1,1) print(a[i]);
221       }
222 
223 
224     return 0;
225 }

 

posted on 2019-10-29 19:25  myx12345  阅读(185)  评论(0编辑  收藏  举报

导航