• POJ1236 SCC缩点+DAG性质


    xg

    题意

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

    思路

      对于强连通分量,可以看作一个整体,然后进行缩点。

      至少提供多少个软件,其实就是求入度为0的点的个数。

      若使得一个DAG成为强连通图,实际就是零入度点的个数和零出度点的个数的最大值。所有都不需要建新图。

      特判一下已经是强连通图的情况。

      

    #include <iostream>
    #include <cmath>
    #include <cstdio>
    #include <cstring>
    #include <string>
    #include <map>
    #include <iomanip>
    #include <algorithm>
    #include <queue>
    #include <stack>
    #include <set>
    #include <vector> 
    #define bug cout<<"--------------"<<endl
    #define sp ' '
    using namespace std;
    typedef long long ll;
    
    const int maxn = 1e5+10;
    int tot = 0;
    int head[maxn],ver[maxn],edge[maxn],nextt[maxn];
    void add(int x,int y)
    {
        ver[++tot] = y,nextt[tot] = head[x] , head[x] = tot;
    }
    int dfn[maxn],low[maxn],sta[maxn],c[maxn],ins[maxn];
    vector<int>scc[maxn];
    
    int in[maxn],out[maxn];
    int n,num,top,cnt;
    void tarjan(int x)
    {
        dfn[x]=low[x]=++num;
        sta[++top]=x,ins[x]=1;
        for(int i=head[x];i;i=nextt[i])
        {
            int y=ver[i];
            if(!dfn[y]){
                tarjan(y);
                low[x]=min(low[x],low[y]);
            }
            else if(ins[y]){
                low[x]=min(low[x],dfn[y]);
            }
            
        }
        if(dfn[x]==low[x]){
            cnt++;int y;
            do{
                y=sta[top--],ins[y]=0;
                c[y]=cnt,scc[cnt].push_back(y);
            }while(x!=y);
        }
    }
    
    int main()
    {
        //freopen("input.txt", "r", stdin);
        scanf("%d",&n);
        for(int i = 1;i <= n; ++i){
            int y ;
            while(scanf("%d",&y)){
                if(y == 0) break;
                add(i,y);
            }
        }
    
        for(int i =1 ;i <=n ;++i){
            if(!dfn[i]) tarjan(i);
        }
        for(int x =1 ;x <=n ;++x){
            for(int i =head[x] ;i;i = nextt[i]){
                int y = ver[i];
                if(c[x] == c[y]) continue;
               // addc(c[x],c[y]);
                in[c[y]]++;
                out[c[x]]++;
            }
        }
        //nub_edge = tc,nub_point = cnt;
        if(cnt == 1) {
            printf("1
    0"); 
            return 0;
        }
        int innub = 0,outnub = 0;
        for(int i = 1;i <= cnt;++i){
            if(!in[i]) innub++;
            if(!out[i]) outnub++;
        }
        printf("%d
    %d",innub,max(innub,outnub) );
    
    
    }

      

  • 相关阅读:
    Gecko SDK (XULRunner SDK)最新版
    北京联通机顶盒-中兴B860A破解
    litepdf简单的PDF操作库
    BZOJ1925 [SDOI2010]地精部落
    BZOJ 最大公约数 (通俗易懂&效率高&欧拉函数)
    Tarjan无向图的割点和桥(割边)全网详解&算法笔记&通俗易懂
    最近公共祖先综合算法笔记
    严格次小生成树[BJWC2010]
    NOIP2016 Day1 T2 天天爱跑步(树上差分,LCA)
    树上差分算法笔记
  • 原文地址:https://www.cnblogs.com/jrfr/p/13546383.html
Copyright © 2020-2023  润新知