POJ 2186 强连通分量
来源:互联网 发布:java电商项目开发源码 编辑:程序博客网 时间:2024/05/18 11:29
比较简单吧。。套模板。。
Gabow
#include "cstdlib" #include "cctype" #include "cstring" #include "cstdio" #include "cmath" #include "algorithm" #include "vector" #include "string" #include "iostream" #include "sstream" #include "set" #include "queue" #include "stack" #include "fstream" #include "strstream" using namespace std;#define M 20000 //题目中可能的最大点数 int STACK[M],top=0; //Gabow 算法中的辅助栈 int STACK2[M],top2=0; // int DFN[M]; //深度优先搜索访问次序 int ComponetNumber=0; //有向图强连通分量个数 int Index=0; //索引号 int Belong[M]; //某个点属于哪个连通分支 vector Edge[M]; //邻接表表示 vector Component[M]; //获得强连通分量结果 bool bcount[M]={0};void Gabow(int i) { int j; DFN[i]=Index++; STACK[++top]=i; STACK2[++top2]=i; for (int e=0;e<Edge[i].size();e++) { j=Edge[i][e]; if (DFN[j]==-1) Gabow(j); else if (Belong[j]==-1) //如果访问过,但没有删除,维护STACK2 { while(DFN[STACK2[top2]]>DFN[j]) //删除构成环的顶点 top2--; } } if(i==STACK2[top2]) //如果Stack2 的顶元素等于i,输出相应的强连通分量 { --top2; ++ComponetNumber; do { Belong[STACK[top]]=ComponetNumber; Component[ComponetNumber].push_back(STACK[top]); }while ( STACK[top--]!=i); } }void solve(int N) //此图中点的个数,注意是0-indexed! { memset(STACK,-1,sizeof(STACK)); memset(STACK2,-1,sizeof(STACK2)); memset(Belong,-1,sizeof(Belong)); memset(DFN,-1,sizeof(DFN)); for(int i=0;i<N;i++) if(DFN[i]==-1) Gabow(i); } void reshape(int N) //缩点形成新图,N为图中的点数 { //bool ComDIG[M][M]; //memset(ComDIG,0,sizeof(ComDIG)); for( int i =0 ; i< N;i++) //一个顶点是i { for(int j=0;j<Edge[i].size();j++) //另外一个顶点是edge[i][j] { if(Belong[i]!=Belong[Edge[i][j]]) bcount[Belong[i]]=true; // ComDIG[Belong[i]][Belong[Edge[i][j]]]=true; } } /*for( int i =1 ;i<=ComponetNumber;i++) { for(int j=1;j<=ComponetNumber;j++) { if(ComDIG[i][j]) cout<<i<<" "<<j<<endl; } }*/} /* 此算法正常工作的基础是图是0-indexed的。但是获得的结果Component数组和Belong数组是1-indexed */ int main() { int n,m; //n个点,m条边 while(scanf("%d %d",&n,&m)==2) { int a,b; int ncount[M]={0}; //定义收缩之后连通分量的出度 for(int i=0;i<m;i++) { scanf("%d %d",&a,&b); a--,b--; Edge[a].push_back(b); } int N=n; solve(N); reshape(N); int time=0,ans=0; for(int i=1;i<=ComponetNumber;i++) if(!bcount[i]) { ans=Component[i].size(); time++; } if(time==1) printf("%d/n",ans); else printf("%d/n",0); } return 0; }
Kosaraju
#include "cstdlib" #include "cctype" #include "cstring" #include "cstdio" #include "cmath" #include "algorithm" #include "vector" #include "string" #include "iostream" #include "sstream" #include "set" #include "queue" #include "stack" #include "fstream" #include "strstream" using namespace std; #define M 20000 bool vis[M]; //遍历数组 int post[M]; //时间戳对应的点 int timestamp; //时间戳 int ComponetNumber=0; //有向图强连通分量个数 int Belong[M]; vector Edge[M]; //邻接表表示 vector Opp[M]; //原图的反图 vector Component[M]; //获得强连通分量结果 bool bcount[M]={0};void dfs(int u) { //第一个dfs确定时间戳 vis[u] = true; for(int i=0;i<Edge[u].size();i++) { if(vis[ Edge[u][i]]) continue; //cout<<Edge[u][i]<<endl; dfs(Edge[u][i]); } //cout<<"timestamp "<<timestamp<<" "<<u<<endl; post[timestamp++] = u; }void dfs2(int u) { //第二个反边dfs确定连通块 vis[u] = true; Component[ComponetNumber].push_back(u); Belong[u]=ComponetNumber; for(int i=0;i<Opp[u].size();i++) { int v = Opp[u][i]; if(vis[v]) continue; dfs2(v); } }void Kosaraju(int n) { memset(Belong,0,sizeof(Belong)); memset(vis,0,sizeof(vis)); timestamp = 0; for(int i=0;i<n;i++) { if(vis[i]) continue; dfs(i); } memset(vis,0,sizeof(vis)); ComponetNumber++; for(int i=n-1;i>=0;i--) {//按时间戳从大到小搜 if(vis[post[i]]) continue; Component[ComponetNumber].clear(); dfs2(post[i]); ComponetNumber++; } ComponetNumber--; //最后我们把块加了1。。所以要减掉 } void reshape(int N) //缩点形成新图,N为图中的点数 { //bool ComDIG[M][M]; //memset(ComDIG,0,sizeof(ComDIG)); for( int i =0 ; i< N;i++) //一个顶点是i { for(int j=0;j<Edge[i].size();j++) //另外一个顶点是edge[i][j] { if(Belong[i]!=Belong[Edge[i][j]]) bcount[Belong[i]]=true; // ComDIG[Belong[i]][Belong[Edge[i][j]]]=true; } } /*for( int i =1 ;i<=ComponetNumber;i++) { for(int j=1;j<=ComponetNumber;j++) { if(ComDIG[i][j]) cout<<i<<" "<<j<<endl; } }*/}// 此算法工作的前提仍然是0-indexed int main() { int n,m; //n个点,m条边 while(scanf("%d %d",&n,&m)==2) { int a,b; int ncount[M]={0}; //定义收缩之后连通分量的出度 for(int i=0;i<m;i++) { scanf("%d %d",&a,&b); a--,b--; Edge[a].push_back(b); Opp[b].push_back(a); } int N=n; Kosaraju(N); reshape(N); int time=0,ans=0; for(int i=1;i<=ComponetNumber;i++) if(!bcount[i]) { ans=Component[i].size(); time++; } if(time==1) printf("%d/n",ans); else printf("%d/n",0); } return 0; }
Tarjan
#include "cstdlib" #include "cctype" #include "cstring" #include "cstdio" #include "cmath" #include "algorithm" #include "vector" #include "string" #include "iostream" #include "sstream" #include "set" #include "queue" #include "stack" #include "fstream" #include "strstream" using namespace std;#define M 10005 //题目中可能的最大点数 int STACK[M],top=0; //Tarjan 算法中的栈 bool InStack[M]; //检查是否在栈中 int DFN[M]; //深度优先搜索访问次序 int Low[M]; //能追溯到的最早的次序 int ComponetNumber=0; //有向图强连通分量个数 int Belong[M]; int Index=0; //索引号 vector Edge[M]; //邻接表表示 vector Component[M]; //获得强连通分量结果 //bool ComDIG[M][M]; bool bcount[M]={0};void Tarjan(int i) { int j; DFN[i]=Low[i]=Index++; InStack[i]=true; STACK[++top]=i; for (int e=0;e<Edge[i].size();e++) { j=Edge[i][e]; if (DFN[j]==-1) { Tarjan(j); Low[i]=min(Low[i],Low[j]); } else if (InStack[j]) Low[i]=min(Low[i],DFN[j]); } if (DFN[i]==Low[i]) { //cout<<"TT "<<i<<" "<<Low[i]<<endl; ComponetNumber++; do { j=STACK[top--]; InStack[j]=false; Component[ComponetNumber].push_back(j); Belong[j]=ComponetNumber; } while (j!=i); } }void solve(int N) //此图中点的个数,注意是0-indexed! { memset(STACK,-1,sizeof(STACK)); memset(InStack,0,sizeof(InStack)); memset(DFN,-1,sizeof(DFN)); memset(Low,-1,sizeof(Low)); memset(Belong,0,sizeof(Belong)); for(int i=0;i<N;i++) if(DFN[i]==-1) Tarjan(i); } void reshape(int N) //缩点形成新图,N为图中的点数 { //bool ComDIG[M][M]; //memset(ComDIG,0,sizeof(ComDIG)); for( int i =0 ; i< N;i++) //一个顶点是i { for(int j=0;j<Edge[i].size();j++) //另外一个顶点是edge[i][j] { if(Belong[i]!=Belong[Edge[i][j]]) bcount[Belong[i]]=true; // ComDIG[Belong[i]][Belong[Edge[i][j]]]=true; } } /*for( int i =1 ;i<=ComponetNumber;i++) { for(int j=1;j<=ComponetNumber;j++) { if(ComDIG[i][j]) cout<<i<<" "<<j<<endl; } }*/} /* 此算法正常工作的基础是图是0-indexed的。 */ int main() { int n,m; //n个点,m条边 while(scanf("%d %d",&n,&m)==2) { int a,b; int ncount[M]={0}; //定义收缩之后连通分量的出度 for(int i=0;i<m;i++) { scanf("%d %d",&a,&b); a--,b--; Edge[a].push_back(b); } int N=n; solve(N); reshape(N); /* for(int i=1;i<=ComponetNumber;i++) { for(int j=0;j<ComponetNumber;j++) { if(ComDIG[i][j]) bcount[i]++; } }*/ int time=0,ans=0; for(int i=1;i<=ComponetNumber;i++) if(!bcount[i]) { ans=Component[i].size(); time++; } if(time==1) printf("%d/n",ans); else printf("%d/n",0); } return 0; }
- POJ 2186 强连通分量
- poj 2186(强连通分量)
- POJ 2186 强连通分量
- poj-2186 强连通分量
- poj 2186 强连通分量
- poj 2186 强连通分量
- POJ 2186 强连通分量 Tarjan算法
- POJ 2186 强连通分量 Targin算法
- POJ 2186-Popular Cows ---强连通分量
- POJ 2186 Popular Cows / 强连通分量
- POJ 2186 Popular Cows 强连通分量
- POJ 2186 Popular Cows (强连通分量)
- poj 2186 强连通分量 缩点
- POJ 2186 Popular Cows (强连通分量)
- POJ 2186 Popular Cows (强连通分量)
- poj 2186 强连通分量个数
- poj 2186 强连通分量Tarjan
- POJ 2186 Popular Cows 强连通分量
- li margin-bottom在IE6,7中底部3像素的BUG
- IE中只读的innerHTML属性
- 卸载 Visual Studio 2005
- 五种开源协议比较
- jQuery从左向右展开DIV(动画效果)
- POJ 2186 强连通分量
- ORACLE函数介绍
- static 静态数据成员 静态成员函数
- vbs处理数组 和 Jmail发送带附件邮件 乱码
- 数据权限如何设计?
- Flex Builder 3的debug错误
- Linux系统如何禁用ping响应
- Python 之 使用全局变量
- 手把手教你写 SQL Join 联接