POJ 1515 双联通分量
Posted Dan__ge
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了POJ 1515 双联通分量相关的知识,希望对你有一定的参考价值。
题意:给一个联通的无向图,然后问你将其中的边变为有向的,加边使其变成有向的联通图
思路:若无向图有双联通分量,那么这个分量里的元素可以变成有向图的强联通,这应该很好看出来,然后需要加的边是什么呢,就是这个图上的桥呗,是桥的话变成有向的就要加一条边,然后剩下的无向图的双联通分量可以用dfs搜一下,边搜边输出就可以了,将桥记录下来遇到桥的时候特殊处理一下,然后双联通分量里的边每一条只能走一次,将走得边和反向边标记一下就行了 PS:vector写这样反向边的真是麻烦
#include <vector> #include <stdio.h> #include <stdlib.h> #include <string.h> #include <iostream> #include <algorithm> using namespace std; typedef long long ll; typedef unsigned long long ull; const int inf=0x3f3f3f3f; const ll INF=0x3f3f3f3f3f3f3f3fll; const int maxn=1050; struct edge{ int to,flag,rev; edge(int a,int b,int c){to=a;flag=b;rev=c;} }; vector<edge>G[maxn]; vector<int>GG[maxn]; int L[maxn],vis[maxn],E[maxn],stack1[maxn]; int n,m,k,kk; void dfs(int x,int fa){ vis[x]=1;L[x]=k;E[x]=k++;stack1[kk++]=x; for(unsigned int i=0;i<G[x].size();i++){ edge t=G[x][i]; if(t.to!=fa){ if(!vis[t.to]){ dfs(t.to,x); L[x]=min(L[x],L[t.to]); }else L[x]=min(L[x],E[t.to]); } } if(L[x]==E[x]){ while(stack1[kk]!=x&&kk>0){ L[stack1[kk-1]]=L[x]; kk--; vis[stack1[kk]]=0; } } } void tarjan(){ memset(E,0,sizeof(E)); kk=0;k=1; for(int i=1;i<=n;i++) if(!E[i]) dfs(i,0); for(int i=1;i<=n;i++){ for(unsigned int j=0;j<G[i].size();j++){ edge t=G[i][j]; if(L[i]!=L[t.to]){ GG[i].push_back(t.to); G[i][j].flag=1; } } } } void print_dfs(int i,int fa){ for(unsigned int j=0;j<G[i].size();j++){ edge t=G[i][j]; if(t.flag||t.to==fa) continue; printf("%d %d\n",i,t.to); G[t.to][t.rev].flag=1; G[i][j].flag=1; if(!vis[t.to]){ vis[t.to]=1; print_dfs(t.to,i); } } } int main(){ int a,b,cas=1; while(scanf("%d%d",&n,&m)!=-1){ if(n==0&&m==0) break; for(int i=0;i<maxn;i++) G[i].clear(); for(int i=0;i<maxn;i++) GG[i].clear(); memset(vis,0,sizeof(vis)); for(int i=0;i<m;i++){ scanf("%d%d",&a,&b); G[a].push_back(edge(b,0,G[b].size())); G[b].push_back(edge(a,0,G[a].size()-1)); } tarjan(); memset(vis,0,sizeof(vis)); printf("%d\n\n",cas++); for(int i=1;i<=n;i++){ if(GG[i].size()==0&&vis[i]==0){ vis[i]=1; print_dfs(i,0); }else{ for(unsigned int j=0;j<GG[i].size();j++){ int t=GG[i][j]; printf("%d %d\n",i,t); } } } puts("#"); } return 0; }
以上是关于POJ 1515 双联通分量的主要内容,如果未能解决你的问题,请参考以下文章
POJ 2942Knights of the Round Table(双联通分量+染色判奇环)