• P2746 [USACO5.3]校园网Network of Schools


    题目地址


    简述:

    • 缩点后进行条件判定.

    易错点:

    • 首先,可以进行缩点.
    • 子任务1:缩点后入度为零的强连通分量必须要有新软件.
    • 子任务2:要求加边后形成一个强连通图。可以考虑到缩点后的DAG上每个点都必须同时具有入度和出度,就可以将没有入度的点的数量记为p,没有出度的点的数量记为q;由于没有出度的点可以直接连接没有入度的点,答案即为max(p,q).

    #include<cstdio>
    #include<iostream>
    #include<vector>
    #include<cstring>
    using namespace std;
    const int MAXN=1000010,MAXM=1000010;
    struct firstEdge1{
        int from,to,nxt;
    }firstEdge[MAXM];
    int firstHead[MAXN],firstEdgeCnt=0;
    void addFirstEdge(int u,int v){
        firstEdge[++firstEdgeCnt].from=u;
        firstEdge[firstEdgeCnt].to=v;
        firstEdge[firstEdgeCnt].nxt=firstHead[u];
        firstHead[u]=firstEdgeCnt;
    }
    int dfn[MAXN],low[MAXN],dfnCnt=0;
    bool inc[MAXN];
    int stck[MAXN],c[MAXN],top=0;
    int sccCnt=0;
    vector<int> sccVec[MAXN];
    void tarjan(int x){
        low[x]=dfn[x]=++dfnCnt;
        inc[x]=1;
        stck[++top]=x;
        for(int i=firstHead[x];i;i=firstEdge[i].nxt){
            int v=firstEdge[i].to;
            if(!dfn[v]){ 
                tarjan(v);
                low[x]=min(low[x],low[v]);
            }else if(inc[v])low[x]=min(low[x],dfn[v]);
        }
        if(dfn[x]==low[x]){
            int y;sccCnt++;
            do{
                y=stck[top--];
                inc[y]=0;
                c[y]=sccCnt;
                sccVec[sccCnt].push_back(y);
            }while(x!=y);
        }
    }
    struct SecondEdge{
        int from,to,nxt;
    }secondEdge[MAXM];
    int secondHead[MAXN],secondEdgeCnt=0;
    void addSecondEdge(int u,int v){
        secondEdge[++secondEdgeCnt].from=u;
        secondEdge[secondEdgeCnt].to=v;
        secondEdge[secondEdgeCnt].nxt=secondHead[secondEdgeCnt];
        secondHead[u]=secondEdgeCnt;
    }
    int rd[MAXN],cd[MAXN];
    int main(){
        int n;
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            int tmp;
            while(true){
                scanf("%d",&tmp);
                if(tmp==0)break;
                addFirstEdge(i,tmp);
            }
        }
        for(int i=1;i<=n;i++)
            if(!low[i])tarjan(i);
        for(int i=1;i<=firstEdgeCnt;i++){
            int u=firstEdge[i].from;
            int v=firstEdge[i].to;
            if(c[u]!=c[v]){
                addSecondEdge(c[u],c[v]);
                rd[c[v]]++;
                cd[c[u]]++;
            }
        }
        int p=0,q=0; 
        for(int i=1;i<=sccCnt;i++){
            if(rd[i]==0)p++;
            if(cd[i]==0)q++;
        } 
        cout<<p<<endl;
        if(sccCnt==1)cout<<"0"<<endl;
        else cout<<max(p,q)<<endl;
        return 0;
    }
  • 相关阅读:
    如何回答十个最棘手的面试问题(下)
    数据库设计三大范式应用实例剖析
    也谈内置无线网卡
    用10个漂亮问题完美结束面试
    Visual C++6.0编译器报错fatal error C1083
    MSDN library下载地址
    如何回答十个最棘手的面试问题(上)
    个人计划永不乱:五款定时提醒软件横评
    怎样使用C#调用exe的应用程序
    组策略妙用通过组策略禁止域用户更改IP地址
  • 原文地址:https://www.cnblogs.com/zbsy-wwx/p/11680595.html
Copyright © 2020-2023  润新知