BZOJ 1051 HAOI 2006 受欢迎的牛

【题解】

  先用tarjan缩点,然后如果某个强联通分量的出度为0,则该强联通分量内的点数为答案,否则无解。因为若其他所有的强联通分量都有边连向Ai,则Ai必定没有出边,否则Ai连向的点所属的强联通分量也属于Ai。

  

#include<cstdio>
#include<algorithm>
#define N (50010)
#define rg register
using namespace std;
int n,m,tot,top,color,ans,last[N],st[N],col[N],dfn[N],low[N],num[N];
int degree_out[N];
struct edge{
	int to,pre;
}e[N];
struct record{
	int u,v;
}r[N];
inline int read(){
	int k=0,f=1; char c=getchar();
	while(c<'0'||c>'9')c=='-'&&(f=-1),c=getchar();
	while('0'<=c&&c<='9')k=k*10+c-'0',c=getchar();
	return k*f;
}
inline int min(int x,int y){return x<y?x:y;}
inline void add(int x,int y){e[++tot]=(edge){y,last[x]}; last[x]=tot;}
void tarjan(int x){
	dfn[x]=low[x]=++tot; st[++top]=x;
	for(rg int i=last[x],to;i;i=e[i].pre)
		if(!dfn[to=e[i].to]) tarjan(to),low[x]=min(low[x],low[to]);
		else if(!col[to]) low[x]=min(low[x],dfn[to]);
	if(dfn[x]==low[x])
		for(color++;st[top+1]!=x;top--) col[st[top]]=color,num[color]++;
}
int main(){
	n=read(); m=read();
	for(rg int i=1,u,v;i<=m;i++) u=read(),v=read(),add(u,v),r[i].u=u,r[i].v=v;
	tot=0;
	for(rg int i=1;i<=n;i++) if(!col[i]) tarjan(i);
	for(rg int i=1,u,v;i<=m;i++){
		u=r[i].u; v=r[i].v;
		if(col[u]!=col[v]) degree_out[col[u]]++;
	}
	int ans=-1;
	for(rg int i=1;i<=color;i++) if(!degree_out[i]){
		printf("%d\n",num[i]);
		return 0;
	}
	puts("0");
	return 0;
}

  

posted @ 2018-02-02 21:02  Driver_Lao  阅读(...)  评论(... 编辑 收藏