记录编号 56937 评测结果 AAAAAAAAAAA
题目名称 [HAOI 2006]受欢迎的牛 最终得分 100
用户昵称 Gravatarcstdio 是否通过 通过
代码语言 C++ 运行时间 0.104 s
提交时间 2013-04-05 09:33:57 内存使用 20.42 MiB
显示代码纯文本
#include<iostream>
#include<cstdio>
#include<cmath>
#include<deque>
using namespace std;
const int SIZEN=10001;
//注意:节点下标是1~n
int n,m;//节点数和边数
deque<int> c[SIZEN];//邻接表
int dfn[SIZEN]={0},low[SIZEN]={0};//喜闻乐见
int index=0;//计时器
deque<int> st;//栈
bool instack[SIZEN]={0};//是否在栈中
int comsum=0;//有多少个分量
int comod[SIZEN]={0},comsize[SIZEN]={0};//每个分量的出度和元素个数
int belong[SIZEN]={0};//每个点属于哪个分量
int out_degree(int x,int k){
	bool used[SIZEN]={0};
	int i,ans=0;
	for(i=0;i<(int)c[x].size();i++){
		if(belong[c[x][i]]==k) continue;
		if(!used[c[x][i]]) used[c[x][i]]=true,ans++;
	}
	return ans;
}
void Tarjan(int x){
	if(dfn[x]) return;
	dfn[x]=low[x]=++index;
	st.push_back(x),instack[x]=true;
	int i,temp;
	for(i=0;i<(int)c[x].size();i++){
		temp=c[x][i];//目前探查的顶点
		if(!dfn[temp]){
			Tarjan(temp);
			low[x]=min(low[x],low[temp]);
		}
		else if(instack[temp]){
			low[x]=min(low[x],dfn[temp]);
		}
	}
	if(dfn[x]==low[x]){//x是分支的一个根
		comsum++;
		i=st.size()-1;
		while(1){
			belong[st[i]]=comsum;
			if(i==0||st[i]==x) break;
			i--;
		}
		while(1){
			temp=st.back();
			comod[comsum]+=out_degree(temp,comsum);
			instack[temp]=false;
			comsize[comsum]++;
			st.pop_back();
			if(st.empty()||temp==x) break;
		}
	}
}
void read(void){
	scanf("%d%d",&n,&m);
	int a,b,i;
	for(i=1;i<=m;i++){
		scanf("%d%d",&a,&b);
		c[a].push_back(b);//a认为b受欢迎
		//"重复的a,b"并不影响DFS
	}
}
void write(void){
	int i;
	int ans=-1;
	bool flag=false;
	for(i=1;i<=comsum;i++){
		if(!comod[i]){
			if(flag){
				printf("0\n");
				return;
			}
			else flag=true,ans=comsize[i];
		}
	}
	printf("%d\n",ans);
}
int main(){
	freopen("cow.in","r",stdin);
	freopen("cow.out","w",stdout);
	read();
	int i;
	for(i=1;i<=n;i++) if(!dfn[i]) Tarjan(i);
	write();
	return 0;
}