题目:航空路线问题
思路:
按每个点拆成
x
i
x_i
xi和
y
i
y_i
yi,并从
y
i
y_i
yi向
x
i
x_i
xi连一条流量为1费用为0的边。
由S向
x
1
x_1
x1连一条流量为2费用为0的边,由
y
n
y_n
yn向T也连一条流量为2费用为0的边。
再根据到达关系,把每个
x
u
x_u
xu和
y
v
y_v
yv间连一条流量为1费用为-1的边(由于求的是最大费用,所以设费用为-1)。
然后在图上求一下最小费用最大流就好,dfs路径输出。
代码:
#include<bits/stdc++.h>
using namespace std;
#define maxm 100000
#define inf (int)1e9
#define read(x) scanf("%d",&x)
struct Edge{
int u,v,w,f;
Edge(){}
Edge(int uu,int vv,int ww,int ff){u=uu,v=vv,w=ww,f=ff;}
};
int n,m;
map<string,int> namelist;
string namelist2[maxm+5];
Edge e[maxm+5];
int h[maxm+5],nxt[maxm+5],cnt=-1;
void addedge(int u,int v,int w,int f) {
e[++cnt]=Edge(u,v,w,f);
nxt[cnt]=h[u];h[u]=cnt;
e[++cnt]=Edge(v,u,0,-f);
nxt[cnt]=h[v];h[v]=cnt;
}
int dist[maxm+5],vis[maxm+5];
queue<int> que;
int pre[maxm+5],minw[maxm+5];
bool spfa() {
for(int i=1;i<=n*2+1;i++) dist[i]=inf,vis[i]=0;
que.push(0);vis[0]=true;minw[0]=inf;
while(!que.empty()) {
int x=que.front();que.pop();
vis[x]=false;
for(int i=h[x];~i;i=nxt[i]) {
Edge y=e[i];
if(y.w>0&&dist[y.v]>dist[x]+e[i].f) {
dist[y.v]=dist[x]+e[i].f;
pre[y.v]=i;
minw[y.v]=min(y.w,minw[y.u]);
if(!vis[y.v]) {
vis[y.v]=true;
que.push(y.v);
}
}
}
}
return dist[n*2+1]!=inf;
}
void update() {
int x=n*2+1;
while(x) {
e[pre[x]].w-=minw[n*2+1];
e[pre[x]^1].w+=minw[n*2+1];
x=e[pre[x]].u;
}
}
int dinic() {
int ans=0;
while(spfa()) {update();ans+=minw[2*n+1]*dist[2*n+1];}
return ans;
}
bool use[maxm+5];
bool dfs1(int x){
if(x==n) return true;
for(int i=h[x];~i;i=nxt[i]) {
if(e[i].w==0&&(!use[e[i].v-n])&&dfs1(e[i].v-n)) {
cout<<namelist2[e[i].u]<<endl;
return true;
}
}
return false;
}
bool dfs2(int x){
if(x==1+n) return true;
for(int i=h[x];~i;i=nxt[i]) {
if(e[i^1].w==0&&dfs2(e[i].v+n)) {
use[e[i].v]=true;
cout<<namelist2[e[i].u-n]<<endl;
return true;
}
}
return false;
}
int main() {
memset(h,-1,sizeof(h));
memset(nxt,-1,sizeof(nxt));
read(n),read(m);
addedge(0,1,2,0);addedge(n*2,n*2+1,2,0);
for(int i=1;i<=n;i++) {
addedge(i+n,i,1,0);
string x;cin>>x;
namelist[x]=i;namelist2[i]=x;
}
bool st=false;
for(int i=1;i<=m;i++) {
string x,y;cin>>x>>y;
int xx=namelist[x],yy=namelist[y];
if(xx>yy) swap(xx,yy);
if(xx==1&&yy==n) st=true;
addedge(xx,yy+n,1,-1);
}
int ans=-dinic();
if(ans<2) {
if(st) cout<<2<<endl<<namelist2[1]<<endl<<namelist2[n]<<endl<<namelist2[1];
else cout<<"No Solution!";
return 0;
}
printf("%d\n",ans);
cout<<namelist2[1]<<endl;
dfs2(n*2);
dfs1(1);
return 0;
}