仅简单介绍下最大费用最大流做法:
1.我们可以把题意转换为:从1城市走两次到n城市,每个城市只能经过一次,最多可经过多少个城市。
2.由于一个中间城市只能到达一次,所以对于中间城市,拆成入点和出点,流量为1;对于1和n,流量为2。
3.由于需要求最多经过的城市数,所以对于每一个城市的入点和拆点之间,可以再连一条费用为1的边,做最大费用流。
4.对于有航班的两个城市,连流量为1,费用为0的边。
5.输出路径,则是考虑一下最大流跑完后,残余网络的性质即可dfs得到。
6.对于有1直接到n的情况,需要做一个特判。
#include <bits/stdc++.h>
using namespace std;
const int N=105,M=1e4+5,inf=2e9;
int n,m,s,t,mincost,ans;
string s1,s2;
map<string,int>id;
string name[N];
int d[N*2];
bool vis[N*2],ff[N*2];
int cnt=1,head[N*2];
struct edge{int next,from,to,w,dis;}e[M*3];
inline void add(int u,int v,int w,int dis)
{
cnt++;
e[cnt].next=head[u];
e[cnt].from=u;
e[cnt].to=v;
e[cnt].w=w;
e[cnt].dis=dis;
head[u]=cnt;
}
inline void insert(int u,int v,int w,int dis)
{
add(u,v,w,dis); add(v,u,0,-dis);
}
queue<int>q;
inline bool spfa()
{
memset(d,-60,sizeof(d));
int maxn=d[0];
memset(vis,false,sizeof(vis));
d[s]=0; vis[s]=true; q.push(s);
while (q.size())
{
int u=q.front(); q.pop();
vis[u]=false;
for (register int i=head[u]; i; i=e[i].next)
if (e[i].w && d[e[i].to]<d[u]+e[i].dis)
{
d[e[i].to]=d[u]+e[i].dis;
if (!vis[e[i].to]) q.push(e[i].to),vis[e[i].to]=true;
}
}
if (d[t]!=maxn) return true;
return false;
}
int dfs(int u,int flow)
{
if (u==t) return flow;
int remain=flow;
ff[u]=true;
for (register int i=head[u]; i; i=e[i].next)
if ((!ff[e[i].to] || e[i].to==t) && e[i].w && d[e[i].to]==d[u]+e[i].dis)
{
int k=dfs(e[i].to,min(e[i].w,remain));
if (!k) {d[e[i].to]=-1; continue;}
e[i].w-=k; e[i^1].w+=k;
mincost+=e[i].dis*k;
remain-=k;
if (!remain) break;
}
return flow-remain;
}
inline int dinic()
{
int ans=0;
while (spfa())
{
memset(ff,false,sizeof(ff));
ans+=dfs(s,inf);
}
return ans;
}
void dfs(int u)
{
cout<<name[u]<<endl;
vis[u]=true;
for (register int i=head[u+n]; i; i=e[i].next)
if (!e[i].w && !vis[e[i].to] && e[i].to<=n)
{
dfs(e[i].to);
break;
}
}
void dfs2(int u)
{
vis[u]=true;
for (register int i=head[u+n]; i; i=e[i].next)
if (!e[i].w && !vis[e[i].to] && e[i].to<=n)
{
dfs2(e[i].to);
break;
}
cout<<name[u]<<endl;
}
int main(){
scanf("%d%d",&n,&m);
s=1,t=n+n;
for (register int i=1; i<=n; ++i)
{
cin>>s1;
name[i]=s1;
id[s1]=i;
if (i==1 || i==n) insert(i,i+n,2,1);
else insert(i,i+n,1,1);
}
bool jay=false;
for (register int i=1; i<=m; ++i)
{
cin>>s1>>s2;
if (id[s1]>id[s2]) swap(s1,s2);
int u=id[s1],v=id[s2];
insert(u+n,v,1,0);
if (u==1 && v==n) jay=true;
}
ans=dinic();
if (ans==2)
{
printf("%d\n",mincost-2);
memset(vis,false,sizeof(vis));
dfs(1);
dfs2(1);
}
else if (ans==1 && jay)
{
printf("%d\n",mincost);
memset(vis,false,sizeof(vis));
dfs(1);
cout<<name[1]<<endl;
}
else puts("No Solution!");
return 0;
}