您的位置:首页 > 其它

51nod 1076 两条不相交的路径 双连通分量

2018-01-19 19:54 447 查看
链接:1076

这个题其实就是每次询问两个点是否同时属于一个边双连通分量,边双连通分量的求法就是删除掉全部桥边之后标记连通块.......

删除掉全部桥边后,两个节点还连通的话一定是双连通的

求全部桥边是一个模板.......然后在遍历标记一下连通块就好了

这个题有个问题,就是节点数较多,直接二维数组标记桥边会内存超出,这里用STL里的set来记录桥边

代码:

#include<bits/stdc++.h>
using namespace std;

const int maxN=25005;
int N;

int pre[maxN];
int low[maxN];
vector<int> all[maxN];
int dfs_clock;
set<long long> isbridge;

long long code(int a,int b){
if(a>b)swap(a,b);
return a*maxN+b;
}

int dfs(int u,int fa){
int lowu=pre[u]=++dfs_clock;
int child=0;
for(int i=0;i<all[u].size();i++){
int v=all[u][i];
if(!pre[v]){
child++;
int lowv=dfs(v,u);
lowu=min(lowu,lowv);
if(lowv>pre[u])isbridge.insert(code(u,v));
}
else if(pre[v]<pre[u]&&v!=fa){
lowu=min(lowu,pre[v]);
}
}
low[u]=lowu;
return lowu;
}

int flag[maxN];
void bfs(int s,int n){
queue<int> q;
q.push(s);
flag[s]=n;
int u,v;
while(!q.empty()){
u=q.front();
q.pop();
for(int i=0;i<all[u].size();i++){
v=all[u][i];
if(flag[v]==0&&isbridge.count(code(u,v))==0){
flag[v]=n;
q.push(v);
}
}
}
}

int main(){
int a,b,m;
cin>>N>>m;
while(m--){
cin>>a>>b;
all[a].push_back(b);
all[b].push_back(a);
}
memset(pre,0,sizeof(pre));
for(int i=1;i<=N;i++)if(pre[i]==0)dfs(i,-1);
memset(flag,0,sizeof(flag));
int cnt=1;
for(int i=1;i<=N;i++)if(flag[i]==0){
bfs(i,cnt++);
}
cin>>m;
while(m--){
cin>>a>>b;
if(flag[a]==flag[b]&&a!=b)cout<<"Yes"<<endl;
else cout<<"No"<<endl;
}
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: