给出一个无向图G的顶点V和边E。进行Q次查询,查询从G的某个顶点V[s]到另一个顶点V[t],是否存在2条不相交的路径。(两条路径不经过相同的边)
(注,无向图中不存在重边,也就是说确定起点和终点,他们之间最多只有1条路)
收起
输入
第1行:2个数M N,中间用空格分开,M是顶点的数量,N是边的数量。(2 <= M <= 25000, 1 <= N <= 50000) 第2 - N + 1行,每行2个数,中间用空格分隔,分别是N条边的起点和终点的编号。例如2 4表示起点为2,终点为4,由于是无向图,所以从4到2也是可行的路径。 第N + 2行,一个数Q,表示后面将进行Q次查询。(1 <= Q <= 50000) 第N + 3 - N + 2 + Q行,每行2个数s, t,中间用空格分隔,表示查询的起点和终点。
输出
共Q行,如果从s到t存在2条不相交的路径则输出Yes,否则输出No。
输入样例
4 4 1 2 2 3 1 3 1 4 5 1 2 2 3 3 1 2 4 1 4
输出样例
Yes Yes Yes No No
思路:求出这个无向图上所有的双联通分量,判断每一对点是不是在一个双联通分量里面,在里面则是Yes,否则是No
代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<vector>
#include<stack>
using namespace std;
const int maxn=50000+10;
int n,m,q;
vector<int> G[maxn], bcc[maxn];
int dfs_clock,bcc_cnt;
int pre[maxn],low[maxn],bccno[maxn];
vector<int> belong[maxn];//belong[i]表示第i个节点属于的所有点双连通分量编号
struct Edge
{
int u,v;
Edge(int u,int v):u(u),v(v) {}
};
stack<Edge> S;
void dfs(int u,int fa)
{
low[u]=pre[u]=++dfs_clock;
for(int i=0; i<G[u].size(); i++)
{
int v=G[u][i];
if(v==fa)
continue;
Edge e=Edge(u,v);
if(!pre[v])
{
S.push(e);
dfs(v,u);
low[u]=min(low[v],low[u]);
if(low[v]>=pre[u])
{
bcc_cnt++;
bcc[bcc_cnt].clear();
while(true)
{
Edge x=S.top();
S.pop();
if(bccno[x.u]!=bcc_cnt)
{
bcc[bcc_cnt].push_back(x.u), bccno[x.u]=bcc_cnt;
belong[x.u].push_back(bcc_cnt);
}
if(bccno[x.v]!=bcc_cnt)
{
bcc[bcc_cnt].push_back(x.v), bccno[x.v]=bcc_cnt;
belong[x.v].push_back(bcc_cnt);
}
if(x.u==u && x.v==v)
break;
}
}
}
else if(pre[v]<pre[u])
{
S.push(e);
low[u]=min(low[u],pre[v]);
}
}
}
int fa[maxn];
int find(int i)
{
if(fa[i]==-1)
return i;
return fa[i]=find(fa[i]);
}
int main()
{
int kase=0;
scanf("%d%d",&n,&m);
bcc_cnt=dfs_clock=0;
memset(pre,0,sizeof(pre));
memset(bccno,0,sizeof(bccno));
memset(fa,-1,sizeof(fa));
for(int i=0; i<n; i++)
G[i].clear(),belong[i].clear();
while(m--)
{
int u,v;
scanf("%d%d",&u,&v);
G[u].push_back(v);
G[v].push_back(u);
u=find(u), v=find(v);
if(u!=v)
fa[u]=v;
}
for(int i=0; i<n; i++)
if(!pre[i])
dfs(i,-1);
scanf("%d",&q);
while(q--)
{
int u,v;
scanf("%d%d",&u,&v);
if(find(u)!=find(v))
printf("No\n");
else
{
bool flag=false;
for(int i=0; i<belong[u].size()&&!flag; i++)
for(int j=0; j<belong[v].size()&&!flag; j++)
{
if(belong[u][i]==belong[v][j])
{
int num=belong[u][i];
if(bcc[num].size()>2)
printf("Yes\n"),flag=true;
}
}
if(!flag)
printf("No\n");
}
}
return 0;
}