记录编号 |
56937 |
评测结果 |
AAAAAAAAAAA |
题目名称 |
[HAOI 2006]受欢迎的牛 |
最终得分 |
100 |
用户昵称 |
cstdio |
是否通过 |
通过 |
代码语言 |
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;
}