强联通块tarjan算法

http://poj.org/problem?id=1236
第一问:需要几个学校存在软件,才能通过传递,使得所有的学校都有软件
用tarjan算法求出强联通分量后,将每个联通分量缩成一个点,那么问题1的答案就是入度为0的点的个数
为什么?入度为0的点,肯定不能通过其他学校传送软件给他,所以他必须存在一份软件
第二问:需要加几条边,才能使得图强联通
缩点后,a为所有入度为0的点的个数,b为所有出度为0的点的个数,那么答案就是max(a,b)

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <vector>
 4 #include <stack>
 5 using namespace std;
 6 const int N = 100 + 10;
 7 vector<int> G[N];
 8 stack<int> st;
 9 bool vis[N];
10 int sccno[N],pre[N],lowlink[N],in[N],out[N],dfs_clock,scc_cnt;
11 int min(const int &a, const int &b)
12 {
13     return a < b ? a : b;
14 }
15 void tarjan(int u)
16 {
17     pre[u] = lowlink[u] = ++dfs_clock;
18     st.push(u);
19     for(int i=0; i<G[u].size(); ++i)
20     {
21         int v = G[u][i];
22         if(!pre[v])
23         {
24             tarjan(v);
25             lowlink[u] = min(lowlink[u],lowlink[v]);
26         }
27         else if(!sccno[v])
28             lowlink[u] = min(lowlink[u],pre[v]);
29     }
30     if(lowlink[u]==pre[u])
31     {
32         scc_cnt++;
33         for(;;)
34         {
35             int x = st.top();st.pop();
36             sccno[x] = scc_cnt;
37             if(x==u) break;
38         }
39     }
40 }
41 void find_scc(int n)
42 {
43     for(int i=1; i<=n; ++i)
44         if(!pre[i])
45             tarjan(i);
46 }
47 int main()
48 {
49     int n,i,a,b;
50     scanf("%d",&n);
51     for(a=1; a<=n; ++a)
52     {
53         while(scanf("%d",&b),b)
54         {
55             G[a].push_back(b);
56             vis[b] = true;
57         }
58     }
59     find_scc(n);
60     for(i=1; i<=scc_cnt; ++i) in[i] = out[i] = 1;
61     for(int u=1; u<=n; ++u)
62         for(i=0; i<G[u].size();++i)
63         {
64             int v = G[u][i];
65             if(sccno[u] != sccno[v]) in[sccno[v]] = out[sccno[u]] = 0;
66         }
67     a = b = 0;
68     for(i=1; i<=scc_cnt; ++i)
69     {
70         if(in[i]) a++;
71         if(out[i]) b++;
72     }
73     int ans = a > b ? a : b;
74     if(scc_cnt == 1) ans = 0;
75     printf("%d\n%d\n",a,ans);
76     return 0;
77 }
时间: 2024-12-06 07:37:35

强联通块tarjan算法的相关文章

hdu2767 Proving Equivalences,有向图强联通,Kosaraju算法

点击打开链接 有向图强联通,Kosaraju算法 缩点后分别入度和出度为0的点的个数 answer = max(a, b); scc_cnt = 1; answer = 0 #include<cstdio> #include<algorithm> #include<vector> #include<cstring> #include<stack> using namespace std; const int maxn = 20000 + 10;

bzoj 2438: [中山市选2011]杀人游戏 (强联通分量 Tarjan)

Description 一位冷血的杀手潜入 Na-wiat,并假装成平民.警察希望能在 N 个人里面,查出谁是杀手. 警察能够对每一个人进行查证,假如查证的对象是平民,他会告诉警察,他认识的人, 谁是杀手, 谁是平民. 假如查证的对象是杀手, 杀手将会把警察干掉. 现在警察掌握了每一个人认识谁. 每一个人都有可能是杀手,可看作他们是杀手的概率是相同的. 问:根据最优的情况,保证警察自身安全并知道谁是杀手的概率最大是多少? Input 第一行有两个整数 N,M. 接下来有 M 行,每行两个整数 x

51nod 1076 2条不相交的路径 无向图强联通分量 trajan算法

1076 2条不相交的路径 基准时间限制:1 秒 空间限制:131072 KB 分值: 40 难度:4级算法题  收藏  关注 给出一个无向图G的顶点V和边E.进行Q次查询,查询从G的某个顶点V[s]到另一个顶点V[t],是否存在2条不相交的路径.(两条路径不经过相同的边) (注,无向图中不存在重边,也就是说确定起点和终点,他们之间最多只有1条路) Input 第1行:2个数M N,中间用空格分开,M是顶点的数量,N是边的数量.(2 <= M <= 25000, 1 <= N <=

POJ 2186-Popular Cows (图论-强联通分量Korasaju算法)

题目链接:http://poj.org/problem?id=2186 题目大意:有n头牛和m对关系, 每一对关系有两个数(a, b)代表a牛认为b牛是“受欢迎”的,且这种关系具有传递性, 如果a牛认为b牛“受欢迎”, b牛认为c牛“受欢迎”, 那么a牛也认为c牛“受欢迎”. 现在想知道有多少头牛受除他本身外其他所有牛的欢迎? 解题思路:如果有两头或者多头牛受除他本身外其他所有牛的欢迎, 那么在这两头或者多头牛之中, 任意一头牛也受两头或者多头牛中别的牛的欢迎, 即这两头或者多头牛同属于一个强联

poj-3177(并查集+双联通分量+Tarjan算法)

题目链接:传送门 思路: 题目要将使每一对草场之间都有至少两条相互分离的路径,所以转化为(一个有桥的连通图至少加几条边才能变为双联通图?) 先将桥删除,然后原图变为多个连通块,每一个连通块就是一个边双联通分量,将双联通子图收缩为一个顶点,再把桥边加回来,边连通度为1, 顺便统计度为1的节点的个数,即叶节点的个数即为cnt,所以至少在树上添加(cnt+1)/2条边. #include<iostream> #include<cstdio> #include<cstring>

POJ 3114 Countries in War(强联通分量+Tarjan)

题目链接 题意 : 给你两个城市让你求最短距离,如果两个城市位于同一强连通分量中那距离为0. 思路 :强连通分量缩点之后,求最短路.以前写过,总感觉记忆不深,这次自己敲完再写了一遍. 1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <vector> 5 #include <stack> 6 #include <queue> 7 #inc

hdu 1269 (强联通分量Tarjan入门)

迷宫城堡 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 10075    Accepted Submission(s): 4529 Problem Description 为 了训练小希的方向感,Gardon建立了一座大城堡,里面有N个房间(N<=10000)和M条通道(M<=100000),每个通道都是单 向的,就是说若称某通道连通

有向图的强联通分量 tarjan

多与DAG上的DP之类的问题一起出现. using namespace std; const int MAXE = 300010; const int MAXP = 100010; struct N { int v,next; }edge[MAXE]; int head[MAXP]; int Top; int ty[MAXP]; int high[MAXP]; int lowlink[MAXP]; int SCCans,dfsclock; int S[MAXP],STop; void InitG

强连通分量的Tarjan算法

资料参考 Tarjan算法寻找有向图的强连通分量 基于强联通的tarjan算法详解 有向图强连通分量的Tarjan算法 处理SCC(强连通分量问题)的Tarjan算法 强连通分量的三种算法分析 Tarjan算法详解理解集合 ppt图解分析下载 强连通分量 强连通分量(strongly connected component)是图论中的概念.图论中,强连通图指每一个顶点皆可以经由该图上的边抵达其他的每一个点的有向图.意即对于此图上每一个点对(Va,Vb),皆存在路径Va→Vb以及Vb→Va.强连通