• USACO network of school 强连通分量


      这个题的意思是有一个有向图, 每个顶点可以发送软件到与其相连的顶点上, 现在问1,至少发送给几个顶点能满足所有顶点都收到软件, 2:如果想让这个图变成强连通图,至少添几条边。  特例是给定的图是一个强连通图的话答案是1, 0. 一般情况下我们先将这个图的强连通分量求出来缩成一个点然后统计入度为0的点和出度为0的点的个数, 答案一就是入度为0的点的个数, 答案就是他们两个之间的最大值。代码如下:

    /*
        ID: m1500293
        LANG: C++
        PROG: schlnet
    */
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <vector>
    
    using namespace std;
    const int max_v = 120;
    
    struct Scc
    {
        int V;           //图的顶点数
        vector<int> G[max_v];    //原始图
        vector<int> rG[max_v];   //反向边的图
        vector<int> vs;          //后序遍历顶点列表
        bool used[max_v];        //访问标记
        int cmp[max_v];          //所属强连通分量的拓扑排序
        void init()
        {
            for(int i=0; i<=V; i++) G[i].clear(), rG[i].clear();
        }
        void add_edge(int from, int to)
        {
            G[from].push_back(to);
            rG[to].push_back(from);
        }
        void dfs(int v)
        {
            used[v] = true;
            for(int i=0; i<G[v].size(); i++)
                if(!used[G[v][i]]) dfs(G[v][i]);
            vs.push_back(v);
        }
        void rdfs(int v, int k)
        {
            used[v] = true;
            cmp[v] = k;
            for(int i=0; i<rG[v].size(); i++)
                if(!used[rG[v][i]]) rdfs(rG[v][i], k);
        }
        int scc()
        {
            memset(used, 0, sizeof(used));
            vs.clear();
            for(int v=1; v<=V; v++)
                if(!used[v]) dfs(v);
            memset(used, 0, sizeof(used));
            int k = 1;
            for(int i=vs.size()-1; i>=0; i--)
                if(!used[vs[i]]) rdfs(vs[i], k++);
            return k-1;
        }
    }ss;
    int num;   //强连通分量的个数
    int in[110], out[110];
    int main()
    {
        freopen("schlnet.in", "r", stdin);
        freopen("schlnet.out", "w", stdout);
        int N;
        scanf("%d", &N);
        ss.V = N;
        ss.init();
        for(int i=1; i<=N; i++)
        {
            int t;
            scanf("%d", &t);
            while(t != 0)
            {
                ss.add_edge(i, t);
                scanf("%d", &t);
            }
        }
    //    printf("%d
    ", ss.scc());
        num = ss.scc();
        if(num == 1)
        {
            printf("1
    0
    ");
            return 0;
        }
        for(int u=1; u<=N; u++)             //u->v
            for(int j=0; j<ss.G[u].size(); j++)
            {
                int v = ss.G[u][j];
                int uu=ss.cmp[u], vv=ss.cmp[v];
                if(uu != vv)
                {
                    in[vv]++;
                    out[uu]++;
                }
            }
        int in_0_num=0, out_0_num=0;
        for(int i=1; i<=num; i++)
        {
            if(!in[i])  in_0_num++;
            if(!out[i]) out_0_num++;
        }
        printf("%d
    %d
    ", in_0_num, max(in_0_num, out_0_num));
        return 0;
    }
  • 相关阅读:
    zoj 1033 与其说是搜索,不如说是枚举
    hdu 4294 数学分析+搜索
    新的篇章
    Silverlight 利用DataGrid行加载事件动态控制行列显示
    (转)Excel中“不同的单元格格式太多”问题解决方法
    EasyUI tree的三种选中状态
    JS监听手机返回键
    Silverlight ComBox获取当前选中项的值
    DataGrdid 利用结果集反向转换成数据List
    silverlight 动态设置下拉框选中值
  • 原文地址:https://www.cnblogs.com/xingxing1024/p/5180641.html
Copyright © 2020-2023  润新知