POJ1236强连通分量tarjan
2012-04-24 14:04
330 查看
//题目大意:给定一个有向图,1.问最少可以从多少个点出发.访问完所有的点. 2.添加最少多少条边可以使得此图为一个强连通图 //解题思路:通过缩点.将该有向图变成一个类似于树的结构..在新的图中.存在一些入度为0和出度为0的特殊点.. // 对于问题1..要能够访问完所有的点..那些入度为0的点是不可能从别的点访问得到的..所以这些点必须从自身开始 // 访问...同时.从这些入度为0的点开始访问以后.其他点入度均不为0, // 所以一定能够从这些点中找到一条路径访问该点 // 问题2..若要使得该图变成一个强连通图.那么入度为0的点和出度为0的点必须全部不存在. // 那么最优的结果就是把入度为0的和出度为0的相连接..这样的结果就一定是max(num(出度为0),num(入度为0)) // 是否一定能够保证图强连通呢? 我们把入度为0的点称作根节点.出度为0的点称作叶子节点 // 那么每个叶子节点必然是由某个根节点出发得到的..而对于每个叶子节点..只要我们把它连出去的边 // 指向不是自己根节点的根节点的话..类似这样的情形 // 根节点1 --> 叶子节点1 . . 根节点2 --> 叶子节点2 根节点3 --> 叶子节点3 // 那么叶子节点1 --> 根节点2 . 就相当于把根节点1 叶子节点1 根节点2 叶子节点2 都连接起来了. // 然后将 叶子节点2 --> 根节点3 . 叶子节点3 --> 根节点1 .. // 这样以后..对于每个叶子节点 , 可以通过其他叶子节点的根到达该叶子节点..这样就可以使得每个 // 叶子节点和根节点都能够到达别的叶子节点和根节点. #include<stdio.h> #include<stdlib.h> #include<string.h> #include<iostream> #include<math.h> #include<vector> #include<queue> #include<stack> using namespace std; const int mn = 111; int LOW[mn],DFN[mn],que[mn],po,visit,belong[mn],res[mn],t,out[mn],in[mn],father[mn],rank[mn]; bool intack[mn]; vector<int>tree[mn]; vector<int>ans[mn]; void Tarjan(int x) { LOW[x] = ++visit; DFN[x] = LOW[x]; que[++po] = x; intack[x] = 1; for(int i = 0 ; i < tree[x].size() ; i++) { int m = tree[x][i]; if(!DFN[m]) { Tarjan(m); LOW[x] = min(LOW[x] , LOW[m]); } else if(intack[m])LOW[x] = min(LOW[x] , DFN[m]); } if(DFN[x] == LOW[x]) { res[++t] = x; int m; do { m = que[po] ; belong[m] = x; po--; intack[m] = 0; }while(m != x); } } void init(int m) { for(int i = 1 ; i <= m ; i++) { father[i] = i; rank[i] = 0; } } int find(int x) { if(x != father[x]) father[x] = find(father[x]); return father[x]; } void Union(int x , int y) { x = find(x); y = find(y); if(x == y)return ; if(rank[x] > rank[y])father[y] = x; else { if(rank[x] == rank[y])rank[y]++; father[x] = y; } } int n; int main() { while(scanf("%d",&n) != EOF) { po = 0;visit = 0;t = 0; memset(belong,0,sizeof(belong)); memset(que,0,sizeof(que)); memset(intack,0,sizeof(intack)); memset(DFN,0,sizeof(DFN)); memset(LOW,0,sizeof(LOW)); memset(in,0,sizeof(in)); memset(out,0,sizeof(out)); memset(res,0,sizeof(res)); init(n); for(int i = 1 ; i <= n ; i++) { tree[i].clear(); ans[i].clear(); } for(int i = 1 ; i <= n ; i++) { int x; while(scanf("%d",&x) && x ) { tree[i].push_back(x); ans[x].push_back(i); } } for(int i = 1 ; i <= n ; i++) if(!DFN[i])Tarjan(i); for(int i = 1 ; i <= n ; i++) Union(i,belong[i]); for(int i = 1 ; i <= n ; i++) { // printf("%d %d\n",i,belong[i]); for(int j = 0 ; j < tree[i].size() ; j++) if(find(i) != find(tree[i][j]))out[belong[i]] ++; for(int j = 0 ; j < ans[i].size() ; j++) if(find(i) != find(ans[i][j]))in[belong[i]] ++; } int ans1 = 0 , ans2= 0; if(t == 1)printf("1\n0\n"); else { for(int i = 1 ; i <= t ; i++) { // printf("%d %d %d\n",res[i],in[res[i]],out[res[i]]); if(!in[res[i]])ans1++; if(!out[res[i]])ans2++; } printf("%d\n%d\n",ans1,max(ans1,ans2)); } } }
相关文章推荐
- Network of Schools POJ - 1236 tarjan强连通分量缩点
- POJ 1236 Network Of Schools ( tarjan求强连通分量 + 缩点成DAG图 )
- 强连通分量,Tarjan,缩点(Network of Schools,POJ 1236)
- [poj 2186]Popular Cows[Tarjan强连通分量]
- 强连通分量 ( Tarjan,邻接链表 )——The Bottom of a Graph ( POJ 2553 )
- poj 1236 scc强连通分量
- poj 1236(tarjam)强连通分量
- poj-1236-一起学习强连通分量
- POJ 1236 Network of Schools 有向图强连通分量
- poj 2186 Popular Cows 有向图强连通分量 tarjan
- King's Quest - POJ 1904 Tarjan强连通分量
- [POJ 3180] The Cow Prom Tarjan求强连通分量 模板题
- poj 2186 Popular Cows(Tarjan,强连通分量缩点)
- poj-1236--一起学习强连通分量2
- poj 2186 Popular Cows 有向图强连通分量 tarjan
- [poj 1904]King's Quest[Tarjan强连通分量]
- Network of Schools POJ - 1236 tarjan强连通分量
- POJ 1236 Network of Schools(强连通 Tarjan+缩点)
- POJ 2186(有向图的强连通分量Tarjan)
- [poj 2553]The Bottom of a Graph[Tarjan强连通分量]