看了题解后:确实不难
开 始 一 直 有 个 小 问 题 , 怎 么 表 示 从 1 到 n 再 回 到 1 开始一直有个小问题,怎么表示从1到n再回到1 开始一直有个小问题,怎么表示从1到n再回到1
实际上等价于1到n的两条不同路径
这 样 就 发 现 可 以 把 1 看 成 源 点 , n 看 成 汇 点 , 构 建 一 条 2 为 最 大 流 的 网 络 这样就发现可以把1看成源点,n看成汇点,构建一条2为最大流的网络 这样就发现可以把1看成源点,n看成汇点,构建一条2为最大流的网络
又 突 然 发 现 每 条 边 每 个 点 只 能 走 一 次 , 当 然 1 和 n 可 以 走 两 次 又突然发现每条边每个点只能走一次,当然1和n可以走两次 又突然发现每条边每个点只能走一次,当然1和n可以走两次
那 就 把 一 个 点 拆 成 两 个 点 , 两 个 点 一 个 负 责 连 入 的 边 , 一 个 负 责 连 出 那就把一个点拆成两个点,两个点一个负责连入的边,一个负责连出 那就把一个点拆成两个点,两个点一个负责连入的边,一个负责连出
两 个 点 间 用 流 量 为 1 的 边 来 限 制 只 能 走 一 次 , 费 用 用 1 代 表 选 了 这 个 节 点 两个点间用流量为1的边来限制只能走一次,费用用1代表选了这个节点 两个点间用流量为1的边来限制只能走一次,费用用1代表选了这个节点
然 后 跑 裸 的 最 大 费 用 最 大 流 然后跑裸的最大费用最大流 然后跑裸的最大费用最大流
输 出 方 案 每 条 路 径 用 一 次 d f s 即 可 输出方案每条路径用一次dfs即可 输出方案每条路径用一次dfs即可
#include <bits/stdc++.h>
using namespace std;
const int inf=1e9;
map<string,int>mp;
map<int,string>cp;
const int maxn=2e5+20;
struct edge{
int to,w,flow,nxt;
}d[maxn]; int head[maxn],cnt=1;
void add(int u,int v,int flow,int w){
d[++cnt]=(edge){v,w,flow,head[u]},head[u]=cnt;
d[++cnt]=(edge){u,-w,0,head[v]},head[v]=cnt;
}
int n,m,s,t;
int dis[maxn],vis[maxn],maxflow,maxcost,flow[maxn],pre[maxn];
bool spfa()
{
queue<int>q;
for(int i=0;i<=t;i++) dis[i]=-inf;
q.push( s ); dis[s]=0;flow[s]=inf;
while( !q.empty() )
{
int u=q.front(); q.pop();
vis[u]=0;
for(int i=head[u];i;i=d[i].nxt )
{
int v=d[i].to;
if( d[i].flow&&dis[v]<dis[u]+d[i].w )
{
dis[v]=dis[u]+d[i].w;
flow[v]=min( flow[u],d[i].flow );
pre[v]=i;
if( !vis[v] ) vis[v]=1,q.push( v );
}
}
}
if( dis[t]==-inf ) return false;
return true;
}
void dinic()
{
while( spfa() )
{
int x=t;
maxflow+=flow[t],maxcost+=flow[t]*dis[t];
while( x!=s )
{
int i=pre[x];
d[i].flow-=flow[t];
d[i^1].flow+=flow[t];
x=d[i^1].to;
}
}
}
void dfs1(int x)
{
vis[x]=1;//表示经过了此节点
cout << cp[x-n] << endl;
for(int i=head[x];i;i=d[i].nxt )
if( d[i].to<=n&&!d[i].flow )
{
dfs1(d[i].to+n);
break;
}
}
void dfs2(int x)
{
for(int i=head[x];i;i=d[i].nxt )
if( d[i].to<=n&&!d[i].flow&&!vis[d[i].to+n] )
{
dfs2(d[i].to+n);
break;
}
cout << cp[x-n] << endl;
}
int main()
{
cin >> n >> m;
for(int i=1;i<=n;i++)
{
string kk; cin >> kk;
mp[kk]=i,cp[i]=kk;
if( i==1 ) add(1,1+n,2,1);
else if( i==n ) add(n,n+n,2,1);
else add(i,i+n,1,1);
}
int flag=0;
for(int i=1;i<=m;i++)
{
string q,w; cin >> q >> w;
int l=mp[q],r=mp[w];
if( l==1&&r==n ) flag=1;
if( l==n&&r==1 ) flag=1;
add(l+n,r,1,0);
}
s=1,t=n+n;
dinic();
if( maxflow==2 )
{
cout << maxcost-2 << endl;
dfs1(1+n);
dfs2(1+n);
}
else if( maxflow==1&&flag )
cout << 2 << "\n" << cp[1] << "\n" << cp[n] << "\n" << cp[1];
else cout << "No Solution!\n";
}