HDU 3836 Equivalent Sets(强连通分量)

题目链接:点击打开链接

思路:强连通分量模板题, 把一个强连通分量的缩成一个点, 构建一张新图。 然后在新图上, 求每个点的入度和出度。 假设有a个顶点的入度为0,b个顶点的出度为0,那么可以证明答案就是max(a, b)。  可以这么想, 入度为0的点肯定要练到出度为0的点。

细节参见代码:

#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <string>
#include <vector>
#include <stack>
#include <bitset>
#include <cstdlib>
#include <cmath>
#include <set>
#include <list>
#include <deque>
#include <map>
#include <queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
typedef long double ld;
const ld eps = 1e-9, PI = 3.1415926535897932384626433832795;
const int mod = 1000000000 + 7;
const int INF = 0x3f3f3f3f;
// & 0x7FFFFFFF
const int seed = 131;
const ll INF64 = ll(1e18);
const int maxn = 20000 + 10;
int T,n,m,u,v,pre[maxn], lowlink[maxn], sccno[maxn], dfs_clock, scc_cnt;
vector<int> g[maxn];
stack<int> S;
void dfs(int u) {
    pre[u] = lowlink[u] = ++dfs_clock;
    S.push(u);
    int len = g[u].size();
    for(int i = 0; i < len; i++) {
        int v = g[u][i];
        if(!pre[v]) {
            dfs(v);
            lowlink[u] = min(lowlink[u], lowlink[v]);
        }
        else if(!sccno[v]) {
            lowlink[u] = min(lowlink[u], pre[v]);
        }
    }
    if(lowlink[u] == pre[u]) {
        scc_cnt++;
        for(;;) {
            int x = S.top(); S.pop();
            sccno[x] = scc_cnt;
            if(x == u) break;
        }
    }
}
void find_scc(int n) {
    for(int i = 1; i <= n; i++) {
        if(!pre[i]) dfs(i);
    }
}
int in0[maxn], out0[maxn];
void init(int n) {
    dfs_clock = scc_cnt = 0;
    for(int i = 1; i <= n; i++) {
        g[i].clear();
        sccno[i] = pre[i] = 0;
    }
}
int main() {
    while(~scanf("%d%d",&n,&m)) {
        init(n);
        for(int i = 1; i <= m; i++) {
            scanf("%d%d",&u,&v);
            g[u].push_back(v);
        }
        find_scc(n);
        if(scc_cnt == 1) { printf("0\n"); continue; }
        for(int i = 1; i <= scc_cnt; i++) in0[i] = out0[i] = 1;
        for(int u = 1; u <= n; u++) {
            int len = g[u].size();
            for(int j = 0; j < len; j++) {
                int v = g[u][j];
                if(sccno[u] != sccno[v]) in0[sccno[v]] = out0[sccno[u]] = 0;
            }
        }
        int a = 0, b = 0;
        for(int i = 1; i <= scc_cnt; i++) {
            if(in0[i]) a++;
            if(out0[i]) b++;
        }
        int ans = max(a, b);
        printf("%d\n", ans);
    }
    return 0;
}
时间: 2024-12-14 02:26:30

HDU 3836 Equivalent Sets(强连通分量)的相关文章

HDU - 3836 Equivalent Sets (强连通分量+DAG)

题目大意:给出N个点,M条边,要求你添加最少的边,使得这个图变成强连通分量 解题思路:先找出所有的强连通分量和桥,将强连通分量缩点,桥作为连线,就形成了DAG了 这题被坑了.用了G++交的,结果一直RE,用C++一发就过了... #include <cstdio> #include <cstring> #define N 20010 #define M 100010 #define min(a,b) ((a) > (b)? (b): (a)) #define max(a,b)

hdu - 3836 Equivalent Sets(强连通)

http://acm.hdu.edu.cn/showproblem.php?pid=3836 判断至少需要加几条边才能使图变成强连通 把图缩点之后统计入度为0的点和出度为0的点,然后两者中的最大值就是需要连的边, 例如,假设入度为0的点多,那么每次把出度为0的点连一条边指向入度为0的点,就构成了一个环, 所以构成了一个强连通分量,同理可得出度为0点多的情况. 这代码用g++ re了,c++才能ac. 1 #include <iostream> 2 #include <cstdio>

HDU 3836 Equivalent Sets(强连通缩点)

Equivalent Sets Problem Description To prove two sets A and B are equivalent, we can first prove A is a subset of B, and then prove B is a subset of A, so finally we got that these two sets are equivalent.You are to prove N sets are equivalent, using

[tarjan] hdu 3836 Equivalent Sets

题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=3836 Equivalent Sets Time Limit: 12000/4000 MS (Java/Others)    Memory Limit: 104857/104857 K (Java/Others) Total Submission(s): 2890    Accepted Submission(s): 1006 Problem Description To prove two set

hdu 3836 Equivalent Sets

题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=3836 Equivalent Sets Description To prove two sets A and B are equivalent, we can first prove A is a subset of B, and then prove B is a subset of A, so finally we got that these two sets are equivalent.Y

hdu 3836 Equivalent Sets(强连通分量--加边)

Equivalent Sets Time Limit: 12000/4000 MS (Java/Others)    Memory Limit: 104857/104857 K (Java/Others) Total Submission(s): 2798    Accepted Submission(s): 962 Problem Description To prove two sets A and B are equivalent, we can first prove A is a su

hdu——3836 Equivalent Sets

Equivalent Sets Time Limit: 12000/4000 MS (Java/Others)    Memory Limit: 104857/104857 K (Java/Others) Total Submission(s): 4782    Accepted Submission(s): 1721 Problem Description To prove two sets A and B are equivalent, we can first prove A is a s

hdu 3836 Equivalent Sets trajan缩点

Equivalent Sets Time Limit: 12000/4000 MS (Java/Others)    Memory Limit: 104857/104857 K (Java/Others) Problem Description To prove two sets A and B are equivalent, we can first prove A is a subset of B, and then prove B is a subset of A, so finally

hdu 3836 Equivalent Sets【强联通】

Equivalent Sets Time Limit: 12000/4000 MS (Java/Others)    Memory Limit: 104857/104857 K (Java/Others) Total Submission(s): 3065    Accepted Submission(s): 1077 Problem Description To prove two sets A and B are equivalent, we can first prove A is a s