您的位置:首页 > 其它

51nod-2条不相交的路径(边双联通分量)

2016-12-22 23:20 441 查看
1076 2条不相交的路径


基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题


 收藏


 关注

给出一个无向图G的顶点V和边E。进行Q次查询,查询从G的某个顶点V[s]到另一个顶点V[t],是否存在2条不相交的路径。(两条路径不经过相同的边)

(注,无向图中不存在重边,也就是说确定起点和终点,他们之间最多只有1条路)

Input
第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,中间用空格分隔,表示查询的起点和终点。


Output
共Q行,如果从s到t存在2条不相交的路径则输出Yes,否则输出No。


Input示例
4 4
1 2
2 3
1 3
1 4
5
1 2
2 3
3 1
2 4
1 4


Output示例
Yes
Yes
Yes
No
No


这道题听说是双联通的模板题(原谅我菜)

由边双联通的定义知:

若一个无向图中的去掉任意一条边都不会改变此图的连通性,即不存在桥,则称作边双连通图。一个无向图中的每一个极大边双连通子图称作此无向图的边双连通分量。

连接两个边双连通分量的边即是桥。
该图只要两点有2条不相交的路径,则这两点必在一个‘类’里

#include<stdio.h>
#include<string.h>
#include<stdlib.h>
#include<iostream>
#include<limits.h>
#include<algorithm>
#include<queue>
#include<stack>
#include<vector>
#include<math.h>
#include<string>
#include<map>
using namespace std;
#define maxn 100005
typedef long long ll;
stack<ll>t;
vector<ll>a[maxn];
ll n,m,time,ans[maxn],vis[maxn],low[maxn],dfn[maxn],type;
//dfn数组标记当前到达该点所需要的时间
void tarjan(ll x,ll y)
{
int i;
low[x]=dfn[x]=time++;
vis[x]=1;
t.push(x);
for(i=0;i<a[x].size();i++)
{
ll v=a[x][i];
if(v==y)
continue;
if(!vis[v])
{
tarjan(v,x);
low[x]=min(low[x],low[v]);
}
else
low[x]=min(low[x],dfn[v]);
}
if(low[x]==dfn[x])
{
type++;
while(t.top()!=x)
{
ans[t.top()]=type;
t.pop();
}
ans[t.top()]=type;
t.pop();
}
}
int  main()
{
ll i,x,y,q;
scanf("%lld%lld",&n,&m);
for(i=1;i<=m;i++)
{
scanf("%lld%lld",&x,&y);
a[x].push_back(y);
a[y].push_back(x);
}
for(i=1;i<=n;i++)
if(!vis[i])
tarjan(i,0);
while(!t.empty())
{
ans[t.top()]=type;
t.pop();
}
scanf("%lld",&q);
for(i=1;i<=q;i++)
{
scanf("%lld%lld",&x,&y);
if(ans[x]==ans[y])
printf("Yes\n");
else
printf("No\n");
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: