强联通分量 缩点 tarjan算法
2014-03-30 13:07
357 查看
/*做一遍DFS,用dfn[i]表示编号为i的节点在DFS过程中的访问序号(也可以叫做开始时间)用low[i]表示i节点DFS过程中i的下方节点所能到达的开始时间最早的节点的开始时间。初始时dfn[i]=low[i] 在DFS过程中会形成一搜索树。在搜索树上越先遍历到的节点,显然dfn的值就越小。 DFS过程中,碰到哪个节点,就将哪个节点入栈。栈中节点只有在其所属的强连通分量已经全部求出时,才会出栈。 如果发现某节点u有边连到搜索树中栈里的节点v,则更新u的low 值为dfn[v](更新为low[v]也可以)。 如果一个节点u已经DFS访问结束,而且此时其low值等于dfn值,则说明u可达的所有节点,都不能到达任何在u之前被DFS访问的节点 ---- 那么该节点u就是一个强连通分量在DFS搜索树中的根。 此时将栈中所有节点弹出,包括u,就找到了一个强连通分量*/ /*本体题意: *有N(N<=10000)头牛,每头牛都想成为most poluler的牛; *给出M(M<=50000)个关系,如(1,2)代表1欢迎2,关系可以传递,但是不可以相互,即1欢迎2不代表2欢迎1; *但是如果2也欢迎3那么1也欢迎3; *给出N,M和M个欢迎关系,求被所有牛都欢迎的牛的数量; *求出强联通分量后,所以解题的方法就应该是在缩点之后的图G中求出所有出度为零的点的个数,如果个数大于1, 说明至少存在两个分量之间的牛不会相互YM,明显和题目要求不符合,输出0,如果等于1则说明只有一个强连通分 量里面的牛被其他全部的牛YM,那么答案就是这个分量中点的个数 */ #include <cstdio> #include <string.h> #include <iostream> #include <algorithm> #include <vector> #define N 50010 using namespace std; int dfs ,instack ,low ,out ,belong ; int stack ; int deep,top,cnt,n,m; vector<int> map ; int min(int a,int b) { return a>b?b:a; } void tarjan(int k) { int i,j; dfs[k]=low[k]=++deep; stack[++top]=k; instack[k]=1; for(i=0; i<map[k].size(); i++) { j=map[k][i]; if(dfs[j]==0) { tarjan(j); low[k]=min(low[k],low[j]); } else if(instack[j]) { low[k]=min(low[k],dfs[j]); } } if(low[k]==dfs[k]) { cnt++; do { j=stack[top--]; belong[j]=cnt; instack[j]=0; } while(j!=k); } } int main() { int i,j,a,b,ans,num,pos; while(scanf("%d%d",&n,&m)!=EOF) { memset(dfs,0,sizeof(dfs)); memset(instack,0,sizeof(instack)); memset(low,0,sizeof(low)); memset(out,0,sizeof(out)); memset(belong,0,sizeof(belong)); memset(stack,0,sizeof(stack)); memset(map,0,sizeof(map)); deep=top=cnt=0; for(i=1; i<=m; i++) { scanf("%d%d",&a,&b); map[a].push_back(b); } for(i=1; i<=n; i++) if(dfs[i]==0) tarjan(i); if(cnt==1) { printf("%d\n",n); continue; } for(i=1; i<=n; i++) for(j=0; j<map[i].size(); j++) if(belong[i]!=belong[map[i][j]]) { out[belong[i]]++; } ans=pos=num=0; for(i=1; i<=cnt; i++) if(!out[i]) { num++; pos=i; } if(num==1) { for(j=1; j<=n; j++) if(belong[j]==pos) { ans++; } printf("%d\n",ans); } else printf("0\n"); } return 0; }
相关文章推荐
- 【POJ 1236 Network of Schools】强联通分量问题 Tarjan算法,缩点
- POJ 2186 Popular Cows(强联通分量缩点+tarjan算法)
- POJ 1236 Network of Schools 强联通分量 + 缩点
- [HAOI2006 受欢迎的牛] 强联通分量 缩点
- 【强联通分量缩点】【最短路】【spfa】bzoj1179 [Apio2009]Atm
- poj2186 Popular Cows (强联通分量+缩点)
- 文章标题 POJ 1236 : Network of Schools (强联通分量+缩点)
- 强连通分量与缩点(Tarjan算法)(洛谷P3387)
- POJ 1236 Network of Schools 强联通分量 + 缩点
- 强联通分量 Tarjan算法
- POJ 3177 Redundant Paths 边双联通分量 缩点
- 强联通分量简讲(Tarjan算法)&&HDU 1269 迷宫城堡
- HDOJ 3861 - The King’s Problem tarjan求强联通分量&缩点&有向图最小路径覆盖(匈牙利)
- bzoj1501受欢迎的牛(强联通分量+缩点)
- 求有向图强联通分量--Tarjan算法
- hdu 4612 Warm up (边双联通分量缩点)
- HDU4612 Warm up(强联通分量+缩点重构图后求树的直径)
- 强联通分量 Tarjan算法 模板
- 文章标题 UVALive 6062:Reduce the Maintenance Cost(双联通分量缩点)
- 强联通分量缩点模板