• POJ 1236 学校网络间的强连通


    题目大意:

    N个学校之间有单向的网络,每个学校得到一套软件后,可以通过单向网络向周边的学校传输。 问题1:初始至少需要向多少个学校发放软件,使得网络内所有的学校最终都能得到软件。 问题2:至少需要添加几条传输线路(边),使任意向一个学校发放软件后,经过若干次传送,网络内所有的学校最终都能得到软件。

    链接http://vjudge.net/problem/viewProblem.action?id=17001

    每个强连通分量内只要有任意一个学校获得一份软件就可以了,因为强连通分量内的任意两点是相互可达的。

    也就是说,在一个强联通分量内的学校可以当作一个学校!

    那么第一问我们所求的就是强连通分量重入度为零的点

    而第二问因为两个强连通合并必然是出度为0的连接入度为0的点,所以要解决掉入度为0,和出度为0的点,所以答案是这两个的最大值(点指缩点)。

    利用scc[i]=scc_cnt 来记录i这个点属于scc_cnt这个连通分量

    总代码如下

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <stack>
    using namespace std;
    #define N 105
    int first[N],scc[N],dfn[N],low[N],degreeIn[N],degreeOut[N],k,n,tmpdfn,scc_cnt;
    stack<int> q;
    struct Path{
        int y,next;
    }path[100005];
    void init()
    {
        memset(first,-1,sizeof(first));
        memset(dfn,0,sizeof(dfn));
        memset(degreeIn,0,sizeof(degreeIn));
        memset(degreeOut,0,sizeof(degreeOut));
        memset(scc,0,sizeof(scc));
        scc_cnt=0,tmpdfn=0,k=0;
    }
    void add(int x,int y)
    {
        path[k].y=y,path[k].next=first[x];
        first[x]=k;
        k++;
    }
    void dfs(int u)
    {
        dfn[u]=low[u]=++tmpdfn;
        q.push(u);
        for(int i=first[u];i!=-1;i=path[i].next){
            int v=path[i].y;
            if(!dfn[v]){
                dfs(v);
                low[u]=min(low[v],low[u]);
            }
            else if(!scc[v]) low[u]=min(low[u],dfn[v]);
        }
        if(low[u]==dfn[u]){
            scc_cnt++;
            for(;;){
                int v=q.top(); q.pop();
                scc[v]=scc_cnt;
                if(u==v) break;
            }
        }
    }
    void get_scc()
    {
        while(!q.empty()) q.pop();
        for(int i=1;i<=n;i++)
            if(!dfn[i]) dfs(i);
        //cout<<"OK"<<endl;
        for(int i=1;i<=n;i++){
            for(int j=first[i];j!=-1;j=path[j].next){
                int v=path[j].y;
                //cout<<v<<endl;
                if(scc[i]!=scc[v]){
                    degreeOut[scc[i]]++;
                    degreeIn[scc[v]]++;
                }
            }
        }
    }
    int main()
    {
        int i,a;
        while(~scanf("%d",&n)){
            int ans1=0,ans2=0;
            init();
            for(i=1;i<=n;i++){
                while(scanf("%d",&a) && a) add(i,a);
            }
            get_scc();
            //for(int i=1;i<=scc_cnt;i++) cout<<degreeIn[i]<<endl;
            //cout<<scc_cnt<<endl;
            for(int i=1;i<=scc_cnt;i++){
                if(!degreeOut[i]) ans1++;
                if(!degreeIn[i]) ans2++;
            }
            ans1=max(ans1,ans2);
            //cout<<"Á¬Í¨·ÖÁ¿£º"<<cnt<<endl;
            if(scc_cnt>1){
                printf("%d
    ",ans2);
                printf("%d
    ",ans1);
            }
            else printf("1
    0
    ");
        }
        return 0;
    }
  • 相关阅读:
    第十三周助教小结
    记事本
    第十二周助教小结
    与周老师会谈之后的感想
    第十一周总结
    第十周助教总结
    听周筠老师一席话,受益匪浅
    2020软件工程作业04
    2020软件工程作业02
    2020软件工程作业01
  • 原文地址:https://www.cnblogs.com/CSU3901130321/p/3894294.html
Copyright © 2020-2023  润新知