题目戳我
本题有一个套路,就是来回一个圈从a到b在到c可以看成从a到b和c,因为这题是网络流所以考虑建图,像这种网络流建图一个点只能通过一次的图,一般情况下都是要拆点的.然后拆点后就要考虑边的容量和cost的分布了,边的容量那么终点和起点都是2其他都是1,cost都为1,因为都是一个点,最后答案再减去2以为起点和终点都经过了两次。如果最后求得的流量是2,说明有两条路径,如果是1的话可能存在1直接到n这种情况,特判一下就好了,其余的都无法到达,具体看代码吧。
#include<iostream>
#include<stdio.h>
#include<math.h>
#include<string.h>
#include<string>
#include<vector>
#include<queue>
#include<algorithm>
#include<deque>
#include<map>
#include<stdlib.h>
#include<set>
#include<iomanip>
#include<stack>
#define ll long long
#define ms(a,b) memset(a,b,sizeof(a))
#define lowbit(x) x & -x
#define fi first
#define ull unsigned long long
#define se second
#define endl "\n"
#define bug cout<<"----acac----"<<endl
#define IOS ios::sync_with_stdio(false), cin.tie(0),cout.tie(0)
using namespace std;
const int maxn =3e3 + 5;
const int maxm = 1.5e5+50;
const double eps = 1e-7;
const double inf = 0x3f3f3f3f;
const double lnf = 0x3f3f3f3f3f3f3f3f;
const int mod = 1e9+7;
const int p=1e7+233;
const double pi=3.141592653589;
string s[105];
map<string,int>mp;
int n,v;
int len,head[maxn];
struct node
{
int fa,to,next,c,cost;
}a[maxn<<2];
void add(int u,int v,int c,int cost)//输入cost的相反数求最大费用流
{
a[len].fa=u,a[len].c=c,a[len].cost=cost,a[len].to=v,a[len].next=head[u],head[u]=len++;
a[len].fa=v,a[len].c=0,a[len].cost=-cost,a[len].to=u,a[len].next=head[v],head[v]=len++;
}
int dis[maxn],vis[maxn],pre[maxn];
bool spfa(int s,int t)
{
queue<int>q;
for(int i=0;i<=t;i++)
{
vis[i]=0;
dis[i]=inf;
pre[i]=-1;
}
dis[s]=0;
q.push(s);
vis[s]=1;
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];~i;i=a[i].next)
{
if(a[i].c>0)
{
int v=a[i].to;
if(dis[v]>dis[u]+a[i].cost)
{
dis[v]=dis[u]+a[i].cost;
pre[v]=i;
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
}//bug;
return dis[t]!=inf;
}
void init()
{
ms(head,-1);
len=0;
}
int flow_sum=0;
int f(int s,int t)//s是源点,t是汇点.
{
int ans=0,flow;
while(spfa(s,t))
{
//bug;
flow=inf;
for(int i=pre[t];~i;i=pre[a[i].fa])
{
if(a[i].c<flow)
flow=a[i].c;
}
for(int i=pre[t];~i;i=pre[a[i].fa])
{
a[i].c-=flow;
a[i^1].c+=flow;
}
ans+=dis[t]*flow;
// printf("%d\n",dis[en]*flow);
flow_sum+=flow;
}
return ans;
}
int pat[maxn];
void dfs1(int x)
{
pat[x]=1;
cout<<s[x-n]<<endl;
for(int i=head[x];i+1;i=a[i].next)
{
int to=a[i].to;
if(to<=n&&!a[i].c)
{
dfs1(to+n);
break;
}
}
}
void dfs2(int x)
{
for(int i=head[x];i+1;i=a[i].next)
{
int to=a[i].to;
if(to<=n&&!a[i].c&&!pat[to+n])
{
dfs2(to+n);
}
}
cout<<s[x-n]<<endl;
}
int main()
{
init();
ms(pat,0);
IOS;
cin>>n>>v;
for(int i=1;i<=n;i++)
{
cin>>s[i];
mp[s[i]]=i;
}
for(int i=2;i<n;i++)
{
add(i,i+n,1,-1);//因为我的模板是最小费用流,而题目意思是最大费用,所以加个负号。
}
bool flage=false;
add(1,n+1,2,-1),add(n,n+n,2,-1);
for(int i=1;i<=v;i++)
{
string a,b;
cin>>a>>b;
int x=mp[a];
int y=mp[b];
if(x>y)swap(x,y);
if(x==1&&y==n)
{
flage=true;
}
add(x+n,y,1,0);//从一个点到另一个点
}
int ans=f(1,2*n);
if(flow_sum==2)
{
cout<<-ans-2<<endl;
}
else if(flow_sum==1&&flage)//特判一下
{
cout<<"2"<<endl;
cout<<s[1]<<" "<<s[n]<<" "<<s[1]<<endl;
return 0;
}
else
{
cout<<"No Solution!"<<endl;
return 0;
}
dfs1(1+n);
dfs2(1+n);
return 0;
}