• codeforce 505 D. Mr. Kitayuta's Technology(tarjan+并查集)


    题目链接:http://codeforces.com/contest/505/problem/D

    题解:先用tarjan缩点然后再用并查集注意下面这种情况

       

    这种情况只需要构成一个大环就行了,也就是说不需要7条边只要6条就够了。

    #include <iostream>
    #include <cstring>
    #include <cstdio>
    #include <vector>
    using namespace std;
    const int M = 2e6 + 10;
    struct Edge {
        int v , next;
    }edge[M];
    int head[M] , e;
    int Low[M] , DFN[M] , Stack[M] , Belong[M];
    int scc;
    int Index , top;
    bool Instack[M];
    int num[M];
    void init() {
        memset(head , -1 , sizeof(head));
        e = 0;
    }
    void add(int u , int v) {
        edge[e].v = v , edge[e].next = head[u] , head[u] = e++;
    }
    void Tarjan(int u) {
        int v;
        Low[u] = DFN[u] = ++Index;
        Stack[top++] = u;
        Instack[u] = true;
        for(int i = head[u] ; i != -1 ; i = edge[i].next) {
            int v = edge[i].v;
            if(!DFN[v]) {
                Tarjan(v);
                Low[u] = min(Low[u] , Low[v]);
            }
            else if(Instack[v]) Low[u] = min(Low[u] , DFN[v]);
        }
        if(Low[u] == DFN[u]) {
            scc++;
            do {
                v = Stack[--top];
                Instack[v] = false;
                Belong[v] = scc;
                num[scc]++;
            }
            while(v != u);
        }
    }
    int f[M] , cnt[M] , flag[M];
    int find(int x) {
        if(x == f[x]) return x;
        int tmp = find(f[x]);
        return f[x] = tmp;
    }
    int main() {
        int n , m;
        scanf("%d%d" , &n , &m);
        init();
        for(int i = 0 ; i < m ; i++) {
            int u , v;
            scanf("%d%d" , &u , &v);
            add(u , v);
        }
        memset(DFN , 0 , sizeof(DFN));
        memset(Instack , false , sizeof(Instack));
        memset(num , 0 , sizeof(num));
        memset(cnt , 0 , sizeof(cnt));
        memset(flag , 0 , sizeof(flag));
        scc = 0 , top = 0 , Index = 0;
        for(int i = 1 ; i <= n ; i++)
            if(!DFN[i]) Tarjan(i);
        for(int i = 1 ; i <= scc ; i++) {f[i] = i; if(num[i] > 1) flag[i] = 1;}
        for(int i = 1 ; i <= n ; i++) {
            for(int j = head[i] ; j != -1 ; j = edge[j].next) {
                int v = edge[j].v;
                if(Belong[i] != Belong[v]) {
                    int a = Belong[i] , b = Belong[v];
                    if(a != b) {
                        int t1 = find(a) , t2 = find(b);
                        if(t1 != t2) {
                            f[t2] = t1;
                            if(num[t2] > 1 || num[t1] > 1) flag[t1] = 1;
                            flag[t1] += flag[t2];
                        }
                    }
                }
            }
        }
        int ans = 0;
        for(int i = 1 ; i <= scc ; i++) {
            ans += num[i];
            f[i] = find(i);
            if(f[i] == i)
                if(!flag[i]) ans--;
        }
        printf("%d
    " , ans);
        return 0;
    }
    
  • 相关阅读:
    Redis-安装
    Redis-介绍
    Redis 教程(转)
    C# Redis 帮助类
    sublime text3---Emmet:HTML/CSS代码快速编写神器
    Sublime Text3 Package Control和Emmet插件安装方法
    vs2010音频文件压缩 调用lame_enc.dll将WAV格式转换成MP3
    vs学习过程中遇见的各种问题
    vs2010中添加dll文件
    解决angular11打包报错Type 'Event' is missing the following properties from type 'any[]': ...Type 'Event' is not assignable to type 'string'
  • 原文地址:https://www.cnblogs.com/TnT2333333/p/6876384.html
Copyright © 2020-2023  润新知