洛谷P2341:https://www.luogu.org/problemnew/show/P2341
这题看错题目 足足花了将近5小时提交了15次 在一位dalao的提醒下才AC了
记得要看清题意啊!
可以成为明星的牛是图中唯一的出度为0的强连通分量中的所有牛
因为如果有两个或以上的话 他们之间无法互相爱慕
即可把所有互相爱慕的牛用Tarjan缩点
判断如果出度为0的强连通分量只有一个 就输出这个强连通分量中的牛数
如果有两个或以上即无解
#include<iostream> #include<cstdio> using namespace std; #define maxn 10010 int n,m,cnt,num,col,top,ans,pd; int dfn[maxn],low[maxn],de[maxn],cow[maxn],f[maxn],st[maxn],h[maxn],co[maxn]; bool vis[maxn]; struct Edge { int to; int next; }e[maxn*5]; void add(int x,int y) { e[++cnt].to=y; e[cnt].next=h[x]; h[x]=cnt; } void Tarjan(int u) { dfn[u]=low[u]=++num; st[++top]=u;//入栈 vis[u]=1;//判断是否在栈中 for(int i=h[u];i;i=e[i].next) { int v=e[i].to; if(!dfn[v]) { Tarjan(v); low[u]=min(low[u],low[v]);//low表示u与其子孙到达的最小编号 } else if(vis[v])//判断v是否在栈中 low[u]=min(low[u],dfn[v]); //可以改成 min(low[u],low[v]) //因为此时v的low和dfn还未修改 } if(dfn[u]==low[u]) { co[u]=++col;//属于第col个强连通分量 ++cow[col];//计算第col个强连通分量中有几头牛 while(st[top]!=u) { ++cow[col]; co[st[top]]=col; vis[st[top--]]=0; } --top; } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); add(x,y); } for(int i=1;i<=n;i++) if(!dfn[i]) Tarjan(i);//缩点 for(int i=1;i<=n;i++)//统计出度 for(int j=h[i];j;j=e[j].next) if(co[i]!=co[e[j].to])//如果不是同一个强连通分量 de[co[i]]++; for(int i=1;i<=col;i++) if(!de[i]) { ans=cow[i];//出度为0 说明这头牛是被所有牛喜欢 pd++; } if(pd==1) printf("%d",ans); else printf("0"); }
【题解】洛谷P2341 [HAOI2006]受欢迎的牛(强连通分量)
原文:https://www.cnblogs.com/BrokenString/p/9688405.html