zoukankan      html  css  js  c++  java
  • 洛谷P2835 刻录光盘

    传送门

    题目大意:有光盘可以传着看,问最少从哪几个人分发,能全部传一遍。

    题解:缩点后求入度为0的点的个数

    代码:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #define maxn 22000
    using namespace std;
    
    int n,sumedge,sumclr,top,tim,ans;
    int Stack[maxn],instack[maxn],low[maxn],dfn[maxn],bel[maxn],rd[maxn],head[maxn];
    
    struct Edge{
        int x,y,nxt;
        Edge(int x=0,int y=0,int nxt=0):
            x(x),y(y),nxt(nxt){}
    }edge[maxn<<1];
    
    void add(int x,int y){
        edge[++sumedge]=Edge(x,y,head[x]);
        head[x]=sumedge;
    }
    
    void Tarjian(int x){
        Stack[++top]=x;instack[x]=true;
        low[x]=dfn[x]=++tim;
        for(int i=head[x];i;i=edge[i].nxt){
            int v=edge[i].y;
            if(instack[v])low[x]=min(low[x],dfn[v]);
            else if(!dfn[v]){
                Tarjian(v);
                low[x]=min(low[x],low[v]);
            }
        }
        if(low[x]==dfn[x]){
            sumclr++;
            while(Stack[top+1]!=x){
                bel[Stack[top]]=sumclr;
                instack[Stack[top]]=false;
                top--;
            }
        }
    }
    
    int main(){
        scanf("%d",&n);
        for(int i=1;i<=n;i++){
            int x;
            while(1){
                scanf("%d",&x);
                if(!x)break;
                add(i,x);
            }
        }
        for(int i=1;i<=n;i++)if(!dfn[i])Tarjian(i);
        for(int x=1;x<=n;x++){
            for(int i=head[x];i;i=edge[i].nxt){
                int v=edge[i].y;
                if(bel[x]!=bel[v])rd[bel[v]]++;
            }
        }
        for(int i=1;i<=sumclr;i++)if(!rd[i])ans++;
        printf("%d
    ",ans);
        return 0;
    }
    AC
  • 相关阅读:
    pandas模块
    27.mysql数据库之约束
    nump模块
    26.mysql数据库基础
    24.IO模型
    23.并发编程之协程
    第五十三篇 并发编程之多进程续
    第五十二篇 操作系统简史——多道技术
    第五十一篇 并发编程——多进程
    第四十九篇 socket套接字编程
  • 原文地址:https://www.cnblogs.com/zzyh/p/7711631.html
Copyright © 2011-2022 走看看