Gym100218I Roundtrip

Link
首先给出一个有解的必要条件:存在\(a\rightarrow c\rightarrow b\)的一条点不相交路径。
必要性是显然的。
注意到保证存在\(3\)\(a\rightarrow b\)的点不相交路径,因此这个条件也具有充分性,具体可以通过调整法证明。
那么我们先用最大流找出三条\(a\rightarrow b\)的路径,然后枚举其中一条作为最后环路中的\(a\rightarrow b\)的路径,再在残量网络(只考虑这一条\(a\rightarrow b\)的路径的流量)上跑出\(a\rightarrow c\rightarrow b\)的路径即可。

#include<queue>
#include<cstdio>
#include<cctype>
#include<vector>
#include<cstring>
#include<algorithm>
const int V=20007,E=220007;
int read(){int x=0,c=getchar();while(isspace(c))c=getchar();while(isdigit(c))(x*=10)+=c&15,c=getchar();return x;}
int n,m,a,b,c,s,t,tot=1,head[V],ver[E],next[E],edge[E],vis[V],pre[V];
std::vector<int>vec[3],pat[3],ans;std::queue<int>q;
void add(int u,int v){ver[++tot]=v,next[tot]=head[u],edge[tot]=1,head[u]=tot,ver[++tot]=u,next[tot]=head[v],head[v]=tot;}
int bfs()
{
    while(!q.empty()) q.pop();
    memset(vis,0,sizeof vis),q.push(s),vis[s]=1;
    for(int i,u,v;!q.empty();) for(i=head[u=q.front()],q.pop();i;i=next[i]) if(edge[i]&&!vis[v=ver[i]]) if(vis[v]=1,pre[v]=i,q.push(v),v==t) return 1;
    return 0;
}
int find()
{
    if(!bfs())return 0;
    for(int p=t;p^s;p=ver[pre[p]^1])--edge[pre[p]],++edge[pre[p]^1];
    return 1;
}
int flow()
{
    int ans=0;
    while(find())++ans;
    return ans;
}
void dfs(int u,std::vector<int>&vec)
{
    if(u<=n) vec.push_back(u);
    if(u==t) return ;
    for(int i=head[u];i;i=next[i]) if(edge[i^1]&&~i&1) {dfs(ver[i],vec),++edge[i],--edge[i^1];break;}
}
int check(int id)
{
    int f=1;
    for(int x:vec[id]) f&=x!=c;
    return f;
}
int main()
{
    freopen("roundtrip.in","r",stdin),freopen("roundtrip.out","w",stdout);
    n=read(),m=read(),a=read(),b=read(),c=read(),s=a+n,t=b;
    for(int i=1,u,v;i<=m;++i) u=read(),v=read(),add(u+n,v),add(v+n,u);
    for(int i=1;i<=n;++i) add(i,i+n);
    for(int i=0;i<3;++i) find();
    for(int i=0;i<3;++i) dfs(s,vec[i]);
    add(a+n,n+n+1),add(b+n,n+n+1),s=c+n,t=n+n+1;
    for(int i=0,f;i<3;++i)
    {
	if(!check(i)) continue;
	for(int j=0;j+1<(int)vec[i].size();++j) for(int k=head[vec[i][j]];k;k=next[k]) if(ver[k]==vec[i][j]+n) edge[k]=0;
	f=flow();
	for(int j=0;j<f;++j) pat[j].clear(),dfs(s,pat[j]);
	if(f==2)
	{
	    if(pat[0].back()==b) std::swap(pat[0],pat[1]);
	    std::reverse(pat[0].begin(),pat[0].end()),ans=pat[0],ans.push_back(c),ans.insert(ans.end(),pat[1].begin(),pat[1].end()),vec[i].pop_back(),std::reverse(vec[i].begin(),vec[i].end()),ans.insert(ans.end(),vec[i].begin(),vec[i].end()),ans.push_back(a),printf("%d\n",(int)ans.size()-1);
	    for(int x:ans) printf("%d ",x);
	    return 0;
	}
	for(int j=0;j+1<(int)vec[i].size();++j) for(int k=head[vec[i][j]];k;k=next[k]) if(ver[k]==vec[i][j]+n) edge[k]=1;	
    }
    puts("-1");
}

猜你喜欢

转载自www.cnblogs.com/cjoierShiina-Mashiro/p/12617397.html