P2341 [HAOI2006]受欢迎的牛
题解
tarjan 缩点板子题
如果 A 稀饭 B,那就 A 向 B 连边,构造出一个有向图
如果这个有向图里有强连通分量,也就说明这个强连通分量里的所有奶牛互相稀饭,他们都有机会成为明星奶牛
但是如果这个有向图里有2个及以上的出度为0的强连通分量,那么就不会有任何一个明星奶牛
所以就是tarjan缩点+寻找出度为0的强连通分量
代码
#include<iostream> #include<cstdio> #include<algorithm> #include<cmath> #include<string> #include<cstring> #include<cstdlib> #include<queue> using namespace std; inline int read() { int ans=0; char last=‘ ‘,ch=getchar(); while(ch<‘0‘||ch>‘9‘) last=ch,ch=getchar(); while(ch>=‘0‘&&ch<=‘9‘) ans=ans*10+ch-‘0‘,ch=getchar(); if(last==‘-‘) ans=-ans; return ans; } const int maxn=50010; int n,m,edge_num=0,tim=0,top=0,qltnum=0; int head[maxn],dfn[maxn],vis[maxn],low[maxn]; int s[maxn],color[maxn],size[maxn],out[maxn]; struct node { int nxt,to; }edge[maxn]; void addedge(int u,int v) { edge_num++; edge[edge_num].to =v; edge[edge_num].nxt =head[u]; head[u]=edge_num; } void tarjan(int x) { dfn[x]=low[x]=++tim; vis[x]=1; s[++top]=x; for(int i=head[x];i;i=edge[i].nxt ) { int y=edge[i].to ; if(!dfn[y]) { tarjan(y); low[x]=min(low[x],low[y]); } else if(vis[y]) low[x]=min(low[x],dfn[y]); } if(dfn[x]==low[x]) { qltnum++; int y; do { y=s[top--]; vis[y]=0; color[y]=qltnum; size[qltnum]++; }while(x!=y); } } int main() { n=read();m=read(); int u,v; for(int i=1;i<=m;i++) { u=read();v=read(); addedge(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].nxt ) { if(color[i]!=color[edge[j].to ]) { out[color[i]]++; } } int now=0; for(int i=1;i<=qltnum;i++) { if(!out[i]) { if(now) { printf("0\n"); return 0; } now=i; } } printf("%d\n",size[now]); return 0; }
原文地址:https://www.cnblogs.com/xiaoyezi-wink/p/11242512.html
时间: 2024-11-05 21:22:47