Popular cattle (strong connected component + shrink point)

Insert picture description here

Idea: To see how many cows are welcomed by all other cows, that is, to see if this point can be reached by all other points, then we ask for his Unicom component. After shrinking the point, we can find that when there is only one Unicom component, the out-degree is At 0, then all points in this Unicom component can be reached by all other points, then the number is the number of points in this Unicom component. When there are more than one point with an out-degree of 0, then none of them can be reached at this time

//#pragma GCC optimize(2)
#include<bits/stdc++.h>
 
using namespace std;
typedef long long ll;
#define SIS std::ios::sync_with_stdio(false)
#define space putchar(' ')
#define enter putchar('\n')
#define lson root<<1
#define rson root<<1|1
typedef pair<int,int> PII;
const int mod=1e9+7;
const int N=1e5+5;
const int inf=0x7f7f7f7f;

int gcd(int a,int b)
{
    
    
    return b==0?a:gcd(b,a%b);
}
 
ll lcm(ll a,ll b)
{
    
    
    return a*(b/gcd(a,b));
}
 
template <class T>
void read(T &x)
{
    
    
    char c;
    bool op = 0;
    while(c = getchar(), c < '0' || c > '9')
        if(c == '-')
            op = 1;
    x = c - '0';
    while(c = getchar(), c >= '0' && c <= '9')
        x = x * 10 + c - '0';
    if(op)
        x = -x;
}
template <class T>
void write(T x)
{
    
    
    if(x < 0)
        x = -x, putchar('-');
    if(x >= 10)
         write(x / 10);
    putchar('0' + x % 10);
}
ll qsm(int a,int b,int p)
{
    
    
    ll res=1%p;
    while(b)
    {
    
    
        if(b&1)
            res=res*a%p;
        a=1ll*a*a%p;
        b>>=1;
    }
    return res;
}
struct node
{
    
    
    int to,nex;
}edge[N];
int n,m;
int head[N],tot,top,scnt,stime;
int low[N],dfn[N],stk[N];
int inst[N],id[N];
int tuan[N],out[N];

void add(int u,int v)
{
    
    
    edge[++tot].to=v;
    edge[tot].nex=head[u];
    head[u]=tot;
}
void tarjan(int u)
{
    
    
   dfn[u]=low[u]=++stime;
   stk[++top]=u;inst[u]=1;
   for(int i=head[u];~i;i=edge[i].nex)
   {
    
    
       int v=edge[i].to;
       if(!dfn[v]){
    
    
           tarjan(v);
           low[u]=min(low[u],low[v]);
       }else if(inst[v]) low[u]=min(low[u],dfn[v]);

   }
   if(dfn[u]==low[u]){
    
    
       int y;++scnt;
       do{
    
    
           y=stk[top--];
           inst[y]=0;
           id[y]=scnt;
           tuan[scnt]++;
       }while(y!=u);
   }

}
int main()
{
    
    
    memset(head,-1,sizeof head);
    cin>>n>>m;
    for(int i=1;i<=m;i++)
    {
    
    
        int u,v;
        cin>>u>>v;
        add(u,v);

    }
    for(int i=1;i<=n;i++)
    {
    
    
        if(!dfn[i]) tarjan(i);
    }
    
    for(int i=1;i<=n;i++)
    for(int j=head[i];~j;j=edge[j].nex)
    {
    
    
        int k=edge[j].to;
        int a=id[i],b=id[k];
        if(a!=b){
    
    
            out[a]++;
        }
    }
    int sum=0,dout=0;
    for(int i=1;i<=scnt;i++){
    
    
        if(!out[i]){
    
    
            sum+=tuan[i];
            dout++;
            if(dout>1){
    
    
                sum=0;break;
            } 
        }
    }
    cout<<sum<<endl;
    

      
   return 0;

}


Guess you like

Origin blog.csdn.net/qq_43619680/article/details/109716756