白书上把这个题归为网络流,可我觉得这个题就是找双连通分量就好。题意就是求能否不经过一些特定路,并经过指定的2条路,然后只能经过每条路和每个点一次,问你是否存在这样的回路。其实找双连通分量就足够了
代码:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<stack>
using namespace std;
const int inf=1<<29;
const int maxn=1100;
const int maxm=maxn*maxn;
int n,m,g[maxn][maxn],au,av,bu,bv;
int e,head[maxn],pnt[maxm],nxt[maxm],dfn[maxn],low[maxn],dfscolck;
bool getans,ans;
struct Edge
{
int from;
int to;
Edge(){}
Edge(int sfrom,int sto)
{
from=sfrom;
to=sto;
}
};
stack<Edge> q;
void AddEdge(int u,int v)
{
pnt[e]=v;nxt[e]=head[u];head[u]=e++;
pnt[e]=u;nxt[e]=head[v];head[v]=e++;
}
void Build()
{
e=0;
memset(head,-1,sizeof(head));
for(int i=1;i<=n;i++)
for(int j=i+1;j<=n;j++)
if(g[i][j])
{
AddEdge(i,j);
AddEdge(j,i);
}
}
int dfs(int u,int f)
{
if(getans)
return 0;
low[u]=dfn[u]=++dfscolck;
for(int i=head[u];i!=-1;i=nxt[i])
{
if(!dfn[pnt[i]])
{
q.push(Edge(u,pnt[i]));
low[u]=min(low[u],dfs(pnt[i],u));
if(getans)
return 0;
if(low[u]>=dfn[u])
{
bool isa=false,isb=false;
for(;;)
{
Edge se=q.top();
q.pop();
if((se.from==au&&se.to==av)||(se.from==av&&se.to==au))
isa=true;
if((se.from==bu&&se.to==bv)||(se.from==bv&&se.to==bu))
isb=true;
if(se.from==u&&se.to==pnt[i])
break;
}
if(isa&&isb)
{
getans=ans=true;
break;
}
}
}
else if(dfn[pnt[i]]<dfn[u]&&pnt[i]!=f)
{
q.push(Edge(u,pnt[i]));
low[u]=min(low[u],dfn[pnt[i]]);
}
}
return low[u];
}
void solve()
{
getans=ans=false;
Build();
dfscolck=0;
memset(dfn,0,sizeof(dfn));
memset(low,0,sizeof(low));
while(!q.empty())
q.pop();
for(int i=1;i<=n;i++)
if(!dfn[i])
dfs(i,-1);
if(ans)
printf("YES\n");
else
printf("NO\n");
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
memset(g,0,sizeof(g));
scanf("%d%d",&n,&m);
for(int i=0;i<m;i++)
{
int u,v;
scanf("%d%d",&u,&v);
g[u][v]=g[v][u]=1;
}
scanf("%d%d",&au,&av);
scanf("%d%d",&bu,&bv);
int k;
scanf("%d",&k);
for(int i=0;i<k;i++)
{
int u,v;
scanf("%d%d",&u,&v);
g[u][v]=g[v][u]=0;
}
solve();
}
return 0;
}