BZOJ1051 [HAOI2006]受欢迎的牛(Tarjan缩点)

题意:

在一个有向图中,求一个点集的大小,这个点集里所有的点都由图中的其他点到达

思路:

这个点集一定是一个强连通分量

先对有向图进行缩点变成DAG,DAG中出度为0的点如果只有一个,那答案就是这个,否则没有答案

/**************************************************************
    Problem: 1051
    User: wrjlinkkkkkk
    Language: C++
    Result: Accepted
    Time:116 ms
    Memory:2724 kb
****************************************************************/
 
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
#include<string>
//#include<stack>
#include<queue>
#include<deque>
#include<set>
#include<vector>
#include<map>
#include<functional>
     
#define fst first
#define sc second
#define pb push_back
#define mem(a,b) memset(a,b,sizeof(a))
#define lson l,mid,root<<1
#define rson mid+1,r,root<<1|1
#define lc root<<1
#define rc root<<1|1
#define lowbit(x) ((x)&(-x)) 
 
using namespace std;
 
typedef double db;
typedef long double ldb;
typedef long long ll;
typedef unsigned long long ull;
typedef pair<int,int> PI;
typedef pair<ll,ll> PLL;
 
const db eps = 1e-6;
const int mod = 100003;
const int maxn = 2e5+100;
const int maxm = 2e5+100;
const ll inf = 0x3f3f3f3f3f3f3f3f;
const db pi = acos(-1.0);
int color[10010],dfn[20020],low[20020],stack[20020],vis[10010],cnt[10010];
int top,n,m,sum,ans;
int deep = 0;
vector<int>g[10010];
vector<int>rg[10010];
void tarjan(int u){
    dfn[u]=++deep;
    low[u]=deep;
    vis[u]=1;
    stack[++top]=u;
    int sz=g[u].size();
    for(int i=0;i<sz;i++){
        int v=g[u][i];
        if(!dfn[v]){
            tarjan(v);
            low[u]=min(low[u],low[v]);
        }
        else{
            if(vis[v]){
                low[u]=min(low[u],low[v]);
            }
        }
    }
    if(dfn[u]==low[u]){
        color[u]=++sum;
        vis[u]=0;
        while(stack[top]!=u){
            color[stack[top]]=sum;
            vis[stack[top--]]=0;
        }
        top--;
    }
    return;
}
int res = 0;
int num[10010];
void rb(){
    for(int i = 1; i <= n; i++){
        num[color[i]]++;
        int sz = g[i].size();
        for(int j = 0; j < sz; j++){
            int u = g[i][j];
            if(color[i]!=color[u]){
                rg[color[i]].pb(color[u]);
            }
        }
    }
    int flg = 0;
    for(int i = 1; i <= sum; i++){
        //printf("%d %d
", i, rg[i].size());
        if(rg[i].size()==0){
            if(flg==0)flg = i;
            else flg = -1;
        }
    }
 
    if(flg==-1)flg = 0;
    else flg = num[flg];
    printf("%d", flg);
}
int main() {
    sum = 0;
    mem(num, 0);
    scanf("%d %d", &n, &m);
    for(int i = 1; i <= m; i++){
        int from, to;
        scanf("%d %d", &from, &to);
        g[from].pb(to);
    }
    for(int i = 1; i <= n; i++){
        if(!dfn[i])tarjan(i);
    }
    //for(int i = 1; i <= n; i++)printf("%d %d
",i, color[i] );
    //printf("%d
", sum);
    rb();
    return 0;
}
原文地址:https://www.cnblogs.com/wrjlinkkkkkk/p/9738957.html