UVa 12167 & HDU 2767 强连通分量 Proving Equivalences

题意:给出一个有向图,问最少添加几条有向边使得原图强连通。

解法:求出SCC后缩点,统计一下出度为0的点和入度为0的点,二者取最大值就是答案。

还有个特殊情况就是本身就是强连通的话,答案就是0.

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <algorithm>
 5 #include <vector>
 6 #include <stack>
 7 using namespace std;
 8
 9 const int maxn = 20000 + 10;
10
11 int n, m;
12
13 vector<int> G[maxn];
14
15 stack<int> S;
16 int pre[maxn], low[maxn], sccno[maxn];
17 int dfs_clock, scc_cnt;
18
19 void dfs(int u, int fa)
20 {
21     low[u] = pre[u] = ++dfs_clock;
22     S.push(u);
23
24     for(int i = 0; i < G[u].size(); i++)
25     {
26         int v = G[u][i];
27         if(!pre[v])
28         {
29             dfs(v, u);
30             low[u] = min(low[u], low[v]);
31         }
32         else if(!sccno[v]) low[u] = min(low[u], pre[v]);
33     }
34
35     if(pre[u] == low[u])
36     {
37         scc_cnt++;
38         for(;;)
39         {
40             int x = S.top(); S.pop();
41             sccno[x] = scc_cnt;
42             if(x == u) break;
43         }
44     }
45 }
46
47 void find_scc()
48 {
49     memset(pre, 0, sizeof(pre));
50     memset(sccno, 0, sizeof(sccno));
51     dfs_clock = scc_cnt = 0;
52     for(int i = 1; i <= n; i++) if(!pre[i]) dfs(i, 0);
53 }
54
55 int in[maxn], out[maxn];
56
57 int main()
58 {
59     int T; scanf("%d", &T);
60     while(T--)
61     {
62         scanf("%d%d", &n, &m);
63         for(int i = 1; i <= n; i++) G[i].clear();
64         while(m--)
65         {
66             int u, v; scanf("%d%d", &u, &v);
67             G[u].push_back(v);
68         }
69
70         find_scc();
71
72         if(scc_cnt == 1) { puts("0"); continue; }
73
74         memset(in, 0, sizeof(in));
75         memset(out, 0, sizeof(out));
76         for(int i = 1; i <= n; i++)
77             for(int j = 0; j < G[i].size(); j++)
78             {
79                 int u = sccno[i], v = sccno[G[i][j]];
80                 if(u != v) { out[u]++; in[v]++; }
81             }
82
83         int hehe = 0, haha = 0;
84         for(int i = 1; i <= scc_cnt; i++)
85         {
86             if(!in[i]) hehe++;
87             if(!out[i]) haha++;
88         }
89         printf("%d\n", max(hehe, haha));
90     }
91
92     return 0;
93 }

代码君

时间: 2024-10-03 11:00:46

UVa 12167 & HDU 2767 强连通分量 Proving Equivalences的相关文章

hdu 4635 强连通分量+缩点

http://acm.hdu.edu.cn/showproblem.php?pid=4635 Problem Description Give a simple directed graph with N nodes and M edges. Please tell me the maximum number of the edges you can add that the graph is still a simple directed graph. Also, after you add

HDU 1269 强连通分量tarjan算法

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

hdu 2767 强连通缩点处理加边问题

#include <cstring> #include <cstdlib> #include <cstdio> 缩点的好处就是可以将乱七八糟的有向图 转化为无环的有向图#include <iostream> #include <algorithm> #include <cmath> #include <stack> using namespace std; #define MAXN 200010 #define clr(x

hdu 3594 强连通分量加环

传送门:Cactus 判断给定的有向图是否满足 1.强连通 2 每一条边属于且仅属于一个环?YES:NO 存在有两种情况(yy一下) 1.他的子节点在栈中 2.他的子节点的最早的时间戳不是他 #include <stdio.h> #include <string.h> #include <vector> #include <stack> #include <algorithm> using namespace std; #define N 200

HDU 2767 强连通缩点

如A能证明B ,就建一条有向边A->B.对于一个能互相证明的一个集合,必然每个2个点都能相互到达,这样的一个集合就是一个强连通集合.我们可以把他们看成一个点,剩下的就是一个DAG图了. 如要都能相互到达,每个点必然出度 >=1, 入度>1 ..所以统计有多少没有入度的点和多少没有出度的点,他们中最大的就是需要添加的边了. VIEW CODE #include<cstdio> #include<cmath> #include<queue> #includ

UVA 12167 - Proving Equivalences(强连通分量+缩点)

UVA 12167 - Proving Equivalences 题目链接 题意:给定一些已经存在的等价性证明,要求全部等价,需要在多最少几次证明 思路:先求出强连通分量,然后进行缩点,在缩点后的图上统计入度和出度为0结点的最大值,就是需要加的边数,注意如果整个图已经是强连通,就直接是答案 代码: #include <cstdio> #include <cstring> #include <vector> #include <stack> #include

hdu 2767 Proving Equivalences(强连通入门题)

1 /************************************************* 2 Proving Equivalences(hdu 2767) 3 强连通入门题 4 给个有向图,求至少加多少条边使得图是所有点都是强连通的 5 由a->b->c->a易知n个点至少要n条边,每个出度和入度都要大 6 于1.先求所有所有强连通分量,把每个强连通分量看成一个点 7 在找每个点的出度和入度,最后还差的出度和入度的最大值就是 8 答案. 9 10 ************

hdu 2767 Proving Equivalences 强连通缩点

给出n个命题,m个推导,问最少增加多少条推导,可以使所有命题都能等价(两两都能互推) 既给出有向图,最少加多少边,使得原图变成强连通. 首先强连通缩点,对于新图,每个点都至少要有一条出去的边和一条进来的边(这样才能保证它能到任意点和任意点都能到它) 所以求出新图中入度为0的个数,和出度为0的个数,添加的边就是从出度为0的指向入度为0的.这样还会有一点剩余,剩余的就乱连就行了. 所以只要求出2者的最大值就OK. #include <iostream> #include<cstring>

HDU 2767 Proving Equivalences(强连通 Tarjan+缩点)

HDU 2767 Proving Equivalences(强连通 Tarjan+缩点) ACM 题目地址:HDU 2767 题意: 给定一张有向图,问最少添加几条边使得有向图成为一个强连通图. 分析: Tarjan入门经典题,用tarjan缩点,然后就变成一个有向无环图(DAG)了. 我们要考虑的问题是让它变成强连通,让DAG变成强连通就是把尾和头连起来,也就是入度和出度为0的点. 统计DAG入度和出度,然后计算头尾,最大的那个就是所求. 代码: /* * Author: illuz <iil