P2341 Luogu [USACO03FALL][HAOI2006]受欢迎的牛 G

国际惯例:题目链接

题目大意:给定有向图,问有多少个点可以被除自己以外所有点到达。

部分分:按照题意模拟,我每个点跑一次\(Dfs\),暴力统计,看看多少个点可以被所有点达到。

感觉也没啥好说的了...\(Tarjan\)缩点,然后发现如果存在这么一坨点,他们必然是出度为\(0\)的,否则的话,这个点如果能回来,就会并入一个\(SCC\),否则的话,这些点必然不满足的。
从而找出度为\(0\)的就好了,如果有多个,也说明必然是无解,否则就记录这一坨点的个数即可。

#include<bits/stdc++.h>
using namespace std;
#define rint register int

//quick in out
inline void in (int &x){
    x = 0; char ch = getchar ();
    while(!isdigit(ch)){ch = getchar () ;}
    while(isdigit(ch))x = x * 10 + ch - 48,ch = getchar () ;
}
void out (int x){
    if(x>9)out(x/10);
    putchar(x%10+48);
}
//end quick in out
const int M = 5e4 + 8 , N = 1e4 + 8;
int n , m;

int h[N] , cnt;
struct Edg{
    int to,nxt;
    inline void add (int u , int v){
        nxt = h[u];
        to = v;
        h[u] = cnt;
    }
}e[M << 1];

/*void add(int u,int v){
    e[++cnt]=(Edg){v,h[u]};
    h[u]=cnt;
}*/

int sta[N] , s , dfn[N] , low[N] , numc , col[N] , tot = 0 , vis[N] , si[N];
void Tarjan (int x){
    sta[++ s] = x ;vis[x] = 1;
    dfn[x] = low[x] = ++ tot ;
    for(rint p = h[x] ; p ; p = e[p].nxt){
        int y = e[p].to;
        if(!dfn[y]){
            Tarjan(y);
            low[x] = min(low[x],low[y]);
        }
        else if(vis[y]){
            //low[x] = min(low[x],dfn[y]);
            low[x] = min(low[x],low[y]);///只有缩点可以使用的写法
        }
    }
    if(dfn[x] == low[x]){
        numc ++;
        while(sta[s + 1] != x){
            si[numc] ++;
            vis[sta[s]] = 0;
            col[sta[s]] = numc;
            s --;
        }
    }
}

int deg[N] , ans = 0;
int main(){
    in(n),in(m);
    for(rint i = 1 ; i <= m ; i ++){
        int a,b;
        in(a) , in(b);
        e[++cnt].add(a , b);
        //add(a,b);
    }
    for(rint i = 1 ; i <= n ; i ++){
        if(dfn[i] == 0)Tarjan(i);
    }
    for(rint i = 1 ; i <= n ; i++){
        int c1 = col[i];
        for(rint p = h[i] ; p ; p =e[p].nxt){
            int c2 = col[e[p].to];
            if(c1 != c2){
                //e[++m].add(c1 , c2);
                deg[c1] ++;
            }
        }
    }
    for(rint i = 1 ; i <= numc ; i ++){
        if(!deg[i]){
            if(ans){
                out(0);
                //printf("0\n");
                return 0;
            }
            ans = si[i];
        }
    }
    out(ans);
    //printf("%d\n",ans);
    return 0;
}

posted @ 2020-12-22 21:20  Z_char  阅读(111)  评论(0编辑  收藏  举报