题意:
思路:
【问题分析】
求最长两条不相交路径,用最大费用最大流解决。
【建模方法】
把第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(" "); 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 ",ans1,ans2); 173 if(ans1==1&&p) 174 { 175 printf("2 "); 176 print(1); 177 print(n); 178 print(1); 179 } 180 181 else if(ans1<2) printf("No Solution! "); 182 else 183 { 184 printf("%d ",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 }