• poj1236


       这题题目意思就是给你n个学校,然后还有这n个学习之间的发送接受关系,然后问你最少需要给多少个学校发送软件可以令全部学校都得到软件,然后又问至少需要加多少条边才能做到,给任意一个学校软件,然后所有学校都得到软件。

      第一问的意思就是问你图上有多少个入度为0的强连通分量。第二问的意思就相当于是问最少需要加多少条边才能使整个图成为一个强连通分量,即是图上任意两点可以到达。做法就是先求出每个强连通分量,然后将每个强连通视为一个缩点(所谓缩点,就这把这个连通分量内的所有点都视为是一个点,相当于是缩小了),然后组成一个dag图,这就将问题转化成要加多少条边才能使这个dag图连通,设入度为0的点的数量为n,出度为0的点的数量为m,那需要加的边数就是max(n,m)因为要将入度为0的点和出度为0的点连接起来。另外还要注意这整个图是一个强连通分量的情况,这时候虽然n=m=1,但是不需要加边,答案是0,这种情况要特批一下。

      

    #include<stdio.h>
    #include<iostream>
    #include<string.h>
    #include<vector>
    using namespace std;
    #define maxn 105
    struct edge
    {
        int to,nxt;
    }e[maxn*maxn];
    int head[maxn],low[maxn],dfn[maxn],sta[maxn],belong[maxn],vis[maxn],num[maxn],rd[maxn],cd[maxn];
    int en,top,scc,n,m,index;
    void addedge(int u,int v)
    {
        e[en].to=v;
        e[en].nxt=head[u];
        head[u]=en++;
    }
    void tarjan(int x)
    {
        int v;
        dfn[x]=low[x]=++index;
        sta[top++]=x;
        vis[x]=1;
        for(int i=head[x];i!=-1;i=e[i].nxt)
        {
            v=e[i].to;
            if(!dfn[v])
            {
                tarjan(v);
                low[x]=min(low[x],low[v]);
            }
            else
                if(vis[v])
                {
                    low[x]=min(low[x],dfn[v]);
                }
        }
        if(low[x]==dfn[x])
        {
            scc++;
            do
            {
                v=sta[--top];
                vis[v]=0;
                belong[v]=scc;
                num[scc]++;
            }while(x!=v);
        }
    }
    int main()
    {
        std::ios::sync_with_stdio(false);
        cin>>n;
        memset(head,-1,sizeof(head));
        memset(low,0,sizeof(low));
        memset(dfn,0,sizeof(dfn));
        memset(vis,0,sizeof(vis));
        memset(rd,0,sizeof(rd));
        memset(cd,0,sizeof(cd));
        memset(num,0,sizeof(num));
        top=0;
        index=0;
        scc=0;
        for(int i=1;i<=n;i++)
        {
            while(1)
            {
                int v;
                cin>>v;
                if(v==0) break;
                addedge(i,v);
            }
        }
        for(int i=1;i<=n;i++)
            if(!dfn[i]) tarjan(i);
        for(int u=1;u<=n;u++)
            for(int i=head[u];i!=-1;i=e[i].nxt)
            {
                int v=e[i].to;
                if(belong[u]!=belong[v])
                {
                    cd[belong[u]]++;
                    rd[belong[v]]++;
                }
    
            }
        int ans1=0,ans2=0;
        for(int i=1;i<=scc;i++)
            if(rd[i]==0) ans1++;
        for(int i=1;i<=scc;i++)
            if(cd[i]==0) ans2++;
        if(scc==1) cout<<1<<endl<<0<<endl;
        else cout<<ans1<<endl<<max(ans1,ans2);
        return 0;
    }
    
  • 相关阅读:
    jquery 移除数组重复的元素----$.unique()
    jQuery UI 日期控件--datepicker
    jQuery 如何设置input checkbox 更有效 prop()
    while loading persisted sessions 异常解决方法
    eclipse总是自动跳到ThreadPoolExecutor.java
    oracle的学习 第二节:创建数据表
    oracle是数据库的学习第一节:数据库的安装
    解决IE无法解析json的方法
    浏览器兼容问题----Firefox不兼容event的解决方法
    VSCode变换python的调试解释器
  • 原文地址:https://www.cnblogs.com/eason9906/p/11755013.html
Copyright © 2020-2023  润新知