zoukankan      html  css  js  c++  java
  • Pku1236 Network of Schools

    n个学校构成一个有向图,通过m条边连接,一:问至少向图中多少个学校投放软件,可以使得所有学校直接或者间接的通过边(假设存在边(u,v),则向u投放v可以得到,而向v投放u不能通过v直接得到)得到软件(假设每次投放的软件无穷多)。二:问至少添加多少条有向边,可以使得只用向任意一个学校投放软件后,别的学校都能得到软件
    输入
    第一行给出数字N,N<=100
    接下来N行给出每个点的连通情况,每行给出一些数字代表第i个学校与哪些学校相连接,每行输入以0代表结束
    输出
    如题

    Sample Input
    5
    2 4 3 0
    4 5 0
    0
    0
    1 0
    Sample Output
    1
    2

    其实就是强连通缩点,
    问一是统计缩点后有多少分量入度为0,
    问二是指至少添加多少边使得图强连通。
    然后统计入度为0的点的个数in和出度为0的点的个数ou,
    则问一输出in,问二如果整个图强连通则输出0,否则输出max{in,ou}。
    为什么是max{in,ou}?
    因为要使得图强连通,则必定每个点的出度以及入度都不为0

    #include<algorithm>
    #include<cstdio>
    using namespace std;
    int son[10100],n,m,ans1,group,low[10100],dfn[10100],st[10100],tot,now[10100],used[11000],popp[11000],topp[11000],a[11000],b[11000],ans2;
    void add(int x,int y)
    {
        tot++;
        now[tot]=son[x];
        son[x]=tot;
    }
    int top,sum,cnt,totle;
    void dfs(int deep)
    {
        st[++top]=deep;
        dfn[deep]=++cnt;
        low[deep]=dfn[deep];
        int nnow=top;
        for(int i=son[deep];i;i=now[i])
            if(!used[b[i]])
            {
                if(!dfn[b[i]])
                    dfs(b[i]);
                low[deep]=min(low[b[i]],low[deep]);
            }
        if(dfn[deep]==low[deep])
        {
            totle++;
            for(int i=nnow;i<=top;i++)
                used[st[i]]=totle;
            top=nnow-1;
        }
    }
    int main()
    {
        int v,k=0;
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&v);
            while(v)
            {
                add(i,v);
                a[++k]=i;
    			b[k]=v;
                scanf("%d",&v);
            }
        }
        for(int i=1;i<=n;i++)
            if(!used[i])dfs(i);
        for(int i=1;i<=k;i++)
            if(used[a[i]]!=used[b[i]])
    		   ++popp[used[a[i]]],
    		   topp[used[b[i]]]++;
        for(int i=1;i<=totle;i++)
        {
            if(topp[i]==0)
    		   ans1++;
            if(popp[i]==0)
    		   ans2++;
        }
        ans2=max(ans1,ans2);
        if(totle==1)
    	   ans2=0;
        printf("%d
    %d",ans1,ans2);
    }
    

      

    #include<cstdio>
    #include<algorithm>
    using namespace std;
    int s[10010],st[110],hea[110],en[110],in[110],dfn[110],low[110],cd[110],rd[110],num,cnt,top,n,m;
    void tarjan(int x)
    {
        low[x]=dfn[x]=++num;
        st[++top]=x;
        for(int i=hea[x];i<en[x];i++)
        {
            int y=s[i];
            if(!dfn[y])
            {
                tarjan(y);
                low[x]=min(low[x],low[y]);
            }
            else if(!in[y])
                low[x]=min(low[x],dfn[y]);
        }
        if(low[x]==dfn[x])
        {
            cnt++;
            while(top&&st[top]!=x)in[st[top--]]=cnt;
            in[st[top--]]=cnt;
        }
    }
    int main()
    {
        scanf("%d",&n);
        for(int i=1;i<=n;i++)
        {
            en[i]=hea[i]=en[i-1];
            while(scanf("%d",s+en[i])&&s[en[i]])en[i]++;
        }
        for(int i=1;i<=n;i++)
            if(!dfn[i])
                tarjan(i);
        for(int i=1;i<=n;i++)
            for(int j=hea[i];j<en[i];j++)
                if(in[i]!=in[s[j]])
                    cd[in[i]]++,rd[in[s[j]]]++;
        int c=0,r=0;
        for(int i=1;i<=cnt;i++)
        {
            if(!cd[i])c++;
            if(!rd[i])r++;
        }
        printf("%d
    ",r);
        if(cnt==1)puts("0");
        else printf("%d
    ",max(c,r));
        return 0;
    }
    

      

  • 相关阅读:
    BZOJ4896 THUSC2016补退选(trie)
    BZOJ4892 Tjoi2017dna(后缀数组)
    BZOJ4890 Tjoi2017城市
    BZOJ4888 Tjoi2017异或和(树状数组)
    BZOJ4887 Tjoi2017可乐(动态规划+矩阵快速幂)
    BZOJ4883 棋盘上的守卫(环套树+最小生成树)
    BZOJ4881 线段游戏(二分图+树状数组/动态规划+线段树)
    BZOJ4878 挑战NP-Hard(dfs树)
    BZOJ5466 NOIP2018保卫王国(倍增+树形dp)
    BZOJ4873 Shoi2017寿司餐厅(最小割)
  • 原文地址:https://www.cnblogs.com/cutemush/p/12660353.html
Copyright © 2011-2022 走看看