• HDU 4635 Strongly connected


    强连通分量+缩点+公式推导

    缩点之后,记录一下每个缩点的真实点有几个,计算一个每个点的入度与出度,然后找出入度或出度为0,并且真实点个数最少的那个缩点,其余的点都可以随便连边了,这个缩点只能单向的向外界连边。

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<vector>
    #include<algorithm>
    using namespace std;
    
    const int maxn = 100000 + 10;
    int Dfn[maxn], U[100000 + 10], V[100000 + 10], Belong[maxn];
    int In[maxn], Out[maxn], flag[maxn];
    int SUM[maxn];
    struct Point
    {
        int id, dfn;
    } point[maxn];
    vector<int>G[maxn];
    vector<int>FG[maxn];
    int N, Tot;
    int M, Block, in, out;
    
    void init()
    {
        for (int i = 0; i<maxn; i++) G[i].clear();
        for (int i = 0; i<maxn; i++) FG[i].clear();
        memset(Dfn, 0, sizeof Dfn);
        memset(In, 0, sizeof In);
        memset(Out, 0, sizeof Out);
        memset(flag, 0, sizeof flag);
        memset(SUM, 0, sizeof SUM);
        memset(Belong, 0, sizeof Belong);
        Tot = 0;//时间戳
        Block = 0;//强连通分量的数目
        in = 0;//统计入度为0的点的数目
        out = 0;//统计出度为0的点的数目
    }
    
    bool cmp(const Point&a, const Point&b)
    {
        return a.dfn>b.dfn;
    }
    
    void Dfs(int now)
    {
        flag[now] = 1;
        for (int i = 0; i<G[now].size(); i++)
        if (!flag[G[now][i]])
            Dfs(G[now][i]);
        Tot++;
        Dfn[now] = Tot;
    }
    
    void dfs(int now)
    {
        Belong[now] = Block;
        for (int i = 0; i<FG[now].size(); i++)
        if (!Belong[FG[now][i]])
            dfs(FG[now][i]);
    }
    
    int main()
    {
        int Case, cAse;
        scanf("%d", &cAse);
        for (Case = 1; Case <= cAse; Case++)
        {
            scanf("%d%d", &N, &M);
            init();
            for (int i = 1; i <= M; i++)
            {
                scanf("%d%d", &U[i], &V[i]);
                G[U[i]].push_back(V[i]);
                FG[V[i]].push_back(U[i]);
            }
            for (int i = 1; i <= N; i++) if (!flag[i]) Dfs(i);    
            for (int i = 0; i<N; i++)
                point[i].id = i + 1, point[i].dfn = Dfn[i + 1];    
            sort(point, point + N, cmp);
            for (int i = 0; i<N; i++)
            if (!Belong[point[i].id])
                Block++, dfs(point[i].id);
            for (int i = 1; i <= M; i++)
            if (Belong[U[i]] != Belong[V[i]])
                Out[Belong[U[i]]]++, In[Belong[V[i]]]++;
            for (int i = 1; i <= N; i++) SUM[Belong[i]]++;
            int St, MMA = 0x7FFFFFFF;
            for (int i = 1; i <= Block; i++)
            if ((!In[i] || !Out[i]) && (SUM[i]<MMA))
                MMA = SUM[i], St = i;
            int MK = 0;
            int ML = 0;
            for (int i = 1; i <= M; i++)
            {
                if (Belong[U[i]] == St && Belong[V[i]] == St) ML++;
                if (Belong[U[i]] == St || Belong[V[i]] == St) continue;
                MK++;
            }
            int Pri = (N - SUM[St])*(N - SUM[St] - 1) - MK + (N - SUM[St])*SUM[St] - max(In[St], Out[St]) + (SUM[St])*(SUM[St] - 1) - ML;
            printf("Case %d: ", Case);
            if (Block == 1) printf("-1
    ");
            else printf("%d
    ", Pri);
        }
        return 0;
    }
  • 相关阅读:
    C++ 内置函数 判断字母、数字及大小写转换
    C++11 随机数 random
    rpc
    C++11 智能指针
    xargs 命令使用
    记录优秀的文章
    腾讯 测试开发
    struts2文件上传、下载、防止重复提交
    注解
    @RestController注解
  • 原文地址:https://www.cnblogs.com/zufezzt/p/4768795.html
Copyright © 2020-2023  润新知