P2341 [HAOI2006]受欢迎的牛
这题的想法确实很巧妙,由于只有除自身外所有奶牛都爱慕奶牛a时,a才是明星奶牛,那么很显然,这说明不可能存在两个不同的强连通分量里都是出度为0,即为明星奶牛的情况,那样就不可能使除自己外所有奶牛爱慕同一强连通分量中的奶牛,so,tarjan+缩点+倒叙查找
代码实现:
1 #include<set> 2 #include<map> 3 #include<list> 4 #include<queue> 5 #include<stack> 6 #include<string> 7 #include<cmath> 8 #include<ctime> 9 #include<vector> 10 #include<bitset> 11 #include<memory> 12 #include<utility> 13 #include<cstdio> 14 #include<sstream> 15 #include<iostream> 16 #include<cstdlib> 17 #include<cstring> 18 #include<algorithm> 19 using namespace std; 20 const int N=50005; 21 22 int n,m,tot,top,z,num,ans,an; 23 int to[N],next[N],head[N],dfn[N],low[N],d[N],s1[N],s2[N],zy[N]; 24 25 inline void add(int x,int y){//加边 26 to[++tot]=y; 27 next[tot]=head[x]; 28 head[x]=tot; 29 } 30 31 void tarjan(int u){//tarjan+缩点 32 dfn[u]=low[u]=++num; 33 s2[++top]=u; 34 for(int i=head[u];i;i=next[i]){ 35 int v=to[i]; 36 if(!dfn[v]){ 37 tarjan(v); 38 low[u]=min(low[u],low[v]); 39 } 40 else{ 41 if(!zy[v]){ 42 low[u]=min(low[u],dfn[v]); 43 } 44 } 45 } 46 if(low[u]==dfn[u]){ 47 zy[u]=++z; 48 s1[z]++; 49 while(s2[top]!=u){ 50 ++s1[z]; 51 zy[s2[top]]=z; 52 top--; 53 } 54 top--; 55 } 56 } 57 58 int main(){ 59 int n,m; 60 scanf("%d%d",&n,&m); 61 for(int i=1;i<=m;i++){ 62 int x,y; 63 scanf("%d%d",&x,&y); 64 add(y,x); 65 } 66 for(int i=1;i<=n;i++){ 67 if(!dfn[i]){ 68 tarjan(i); 69 } 70 } 71 for(int i=1;i<=n;i++){//遍历每个节点的出度 72 for(int j=head[i];j;j=next[j]){ 73 if(zy[i]!=zy[to[j]]){ 74 d[zy[to[j]]]++; 75 } 76 } 77 } 78 for(int i=1;i<=z;i++){ 79 if(!d[i]){//若出度为0,记录 80 ans=s1[i]; 81 an++; 82 } 83 } 84 if(an==1){ 85 printf("%d\n",ans); 86 } 87 else{//多个出度为0则无明星奶牛 88 printf("0\n"); 89 } 90 return 0; 91 }
嗯我要睡觉了白白