• Equivalent Sets HDU


    题目说给出一些子集,如果A是B的子集,B是A的子集,那么A和B就是相等的,然后给出n个集合m个关系,m个关系表示u是v的子集,问你最小再添加多少个关系可以让这n个集合都是相等的

    如果这n个几个都是互相相等的,那么就等于是这n个集合看成点以后,构成的图是一个强连通图,那么就是说在加多少边让这个图变成强联通图。

    先缩点然后做判断

    1,如果原本的图本来就是强联通的,那么答案就是0

    2.如果原本的图不是强联通的,那就去判断缩完以后的点的入度和出度,取入度为0的和出度为0的点数的最大值,就是最小需要加的边

    #include<map>
    #include<set>
    #include<ctime>
    #include<cmath>
    #include<stack>
    #include<queue>
    #include<string>
    #include<vector>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #define lowbit(x) (x & (-x))
    
    typedef unsigned long long int ull;
    typedef long long int ll;
    const double pi = 4.0*atan(1.0);
    const int inf = 0x3f3f3f3f;
    const int maxn = 20005;
    const int maxm = 50005;
    const int mod = 10007;
    using namespace std;
    
    int n, m, tol, T;
    int cnt, sz, top;
    struct Node {
        int u, v;
        int next;
    };
    Node node[maxm];
    int head[maxn];
    int dfn[maxn];
    int low[maxn];
    int ind[maxn];
    int oud[maxn];
    int sta[maxn];
    int point[maxn];
    bool vis[maxn];
    
    void init() {
        tol = cnt = top = sz = 0;
        memset(dfn, 0, sizeof dfn);
        memset(low, 0, sizeof low);
        memset(ind, 0, sizeof ind);
        memset(oud, 0, sizeof oud);
        memset(vis, 0, sizeof vis);
        memset(head, -1, sizeof head);
        memset(point, 0, sizeof point);
    }
    
    void addnode(int u, int v) {
        node[tol].u = u;
        node[tol].v = v;
        node[tol].next = head[u];
        head[u] = tol++;
    }
    
    void dfs(int u) {
        int v;
        dfn[u] = low[u] = ++cnt;
        sta[sz++] = u;
        vis[u] = true;
        for(int i=head[u]; ~i; i=node[i].next) {
            v = node[i].v;
            if(!dfn[v]) {
                dfs(v);
                low[u] = min(low[u], low[v]);
            } else if(vis[v]) {
                low[u] = min(low[u], dfn[v]);
            }
        }
        if(dfn[u] == low[u]) {
            top++;
            do {
                v = sta[--sz];
                point[v] = top;
                vis[v] = false;
            } while(v != u);
        }
    }
    
    void tarjan() {
        for(int u=1; u<=n; u++) {
            if(!dfn[u])    dfs(u);
        }
    }
    
    void solve() {
        for(int u=1; u<=n; u++) {
            for(int i=head[u]; ~i; i=node[i].next) {
                int v = node[i].v;
                if(point[u] != point[v]) {
                    ind[point[v]]++;
                    oud[point[u]]++;
                }
            }
        }
    }
    
    int main() {
        while(~scanf("%d%d", &n, &m)) {
            init();
            int u, v;
            for(int i=1; i<=m; i++) {
                scanf("%d%d", &u, &v);
                addnode(u, v);
            }
            tarjan();
    //        for(int i=1; i<=n; i++)    printf("!!!!%d %d
    ", i, point[i]);
            if(top == 1) {
                printf("0
    ");
                continue;
            }
            solve();
            int ans1=0, ans2=0;
            memset(vis, 0, sizeof vis);
            for(int i=1; i<=top; i++) {
                if(ind[i] == 0)    ans1++;
                if(oud[i] == 0)    ans2++;
            }
            printf("%d
    ", max(ans1, ans2));
        }
        return 0;
    }
    View Code
  • 相关阅读:
    xtrabackup详细用法
    CentOS国内YUM源及配置
    CentOS7系统配置国内yum源和epel源
    Zabbix的定期备份
    Zabbix的邮件告警
    石头剪刀布---组合数取模,数论
    组合数取模介绍----Lucas定理介绍
    乘法逆元
    费马小定理
    欧几里德与扩展欧几里德算法----数论
  • 原文地址:https://www.cnblogs.com/Jiaaaaaaaqi/p/9397802.html
Copyright © 2020-2023  润新知