(网络流24题大多需要spj,所以需要一个有spj的oj,本系列代码均在www.oj.swust.edu.cn测试通过)
这道题我们首先要想明白的是飞机往返飞两次其实等价于两架飞机走一次,只要两架飞机的路线除出发点和结束点以外不重合即可。那么我们只要将每个点拆分成两个点,点与点之间连一条容量为1,费用为1(起始点和结束点的容量为2)的流即可,跑一边最大费用最大流就行了。个人觉得最难的还是输出路径的问题,我用的方法是重新检索图中的边查看哪些流过了再加一些特判输出,写的挺麻烦的,要是有更好的办法欢迎提出来。
对了,这题还有个坑,就是图中只有起始点和结束点的时候,这时路径即为起始点-结束点-起始点,特判掉就可以了。
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
bool pd[100000];
bool ps[100000];
struct bian
{
int l,r,f,v,lei;
}a[1000000];
int fir[1000000];
int nex[1000000];
int tot=1;
void add_edge(int l,int r,int f,int v,int lei=0)
{
a[++tot].l=l;
a[tot].r=r;
a[tot].f=f;
a[tot].v=v;
a[tot].lei=lei;
nex[tot]=fir[l];
fir[l]=tot;
}
int s=0,t=999;
int fro[1000];
int juli[1000];
bool spfa()
{
static int dui[1000000];
memset(juli,0x8f,sizeof(juli));
int top=1,my_final=2;
dui[top]=s;
pd[s]=true;
juli[s]=0;
while(topint u=dui[top++];
for(int o=fir[u];o;o=nex[o])
{
if(juli[a[o].r]if(!pd[a[o].r]) pd[a[o].r]=true,dui[my_final++]=a[o].r;
}
}
pd[u]=false;
}
if(juli[t]==0x8f8f8f8f) return false;
return true;
}
int add_flow()
{
int o=t;
int temp=2147483647;
while(o!=s)
{
temp=min(temp,a[fro[o]].f);
o=a[fro[o]^1].r;
}
o=t;
while(o!=s)
{
a[fro[o]].f-=temp;
a[fro[o]^1].f+=temp;
o=a[fro[o]^1].r;
}
return temp;
}
string ss[101];
map<string,int> mapp1;
map<int,string> mapp2;
string mid;
int main()
{
int n,m;
scanf("%d%d",&n,&m);
for(int i=1;i<=n;i++)
{
if(i!=1 && i!=n)
{
add_edge(2*i,2*i+1,1,1,1);
add_edge(2*i+1,2*i,0,-1);
}
else
{
add_edge(2*i,2*i+1,2,1,1);
add_edge(2*i+1,2*i,0,-1);
}
cin>>ss[i];
mapp1[ss[i]]=i;
mapp2[i]=ss[i];
}
add_edge(s,2,2,0,1);
add_edge(2,s,0,0);
add_edge(2*n+1,t,2,0,1);
add_edge(t,2*n+1,0,0);
bool spj=false;
for(int i=1;i<=m;i++)
{
cin>>mid;
int x=mapp1[mid];
cin>>mid;
int y=mapp1[mid];
add_edge(2*x+1,2*y,1,0,1);
add_edge(2*y,2*x+1,0,0);
if((x==1 && y==n) || (x==n && y==1)) spj=true;
}
int ans=0;
int cost=0;
while(spfa())
{
int k=add_flow();
cost+=juli[t]*k;
ans+=k;
}
if(ans!=2)
{
if(spj) cout<<2<1]<1];
else cout<<"No Solution!";
}
else
{
cout<2<int k=s;
while(k!=t)
{
for(int o=fir[k];o;o=nex[o])
if(a[o].lei && a[o].f==0)
{
k=a[o].r;
if(!ps[a[o].r>>1] && mapp2[a[o].r>>1].size()!=0) cout<>1]<>1]=true;
if(a[o^1].f!=2) pd[o]=true;
break;
}
}
while(k!=s)
{
for(int o=fir[k];o;o=nex[o])
{
if(a[o^1].lei && !a[o^1].f && !pd[o^1])
{
k=a[o].r;
if(!ps[a[o].r>>1] && mapp2[a[o].r>>1].size()!=0) cout<>1]<>1]=true;
break;
}
}
}
cout<1]<return 0;
}