1. 程式人生 > 實用技巧 >P2341 Luogu [USACO03FALL][HAOI2006]受歡迎的牛 G

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;
}