显然做法就是建反图,每个点都遍历一下,然后能过
然而有几个点死能卡常数,怎么办呢
干他
如果一头牛不能到达所有奶牛,它能到的所有牛都不行,同理,如果一头奶牛可以,它能到的所有牛都行
然而,这么干还是会被最后一个点干掉。
采用vector,对于每一个点的出边从小到大排序,因为最后枚举是从从小到大的,显然这么干更容易让上优化起效
就干过去了
include
include
include
include
using namespace std;
int n,m;
int vis[10005];
vector
int x,y;
int sit[10005];
int head[10005];
int p;
int f=0;
int cnt;
void dfs(int no){
if(vis[no]||f) return;
vis[no]=1;cnt++;
if(sit[no]1){
cnt=n;
f=1;
return ;
}
for(int i=0;i<head[no];i++){
dfs(ed[no][i]);
if(f)
return ;
}
}
int ans;
int main(){
scanf("%d%d",&n,&m);
cnt=n;
for(int i=1;i<=m;++i){
scanf("%d%d",&x,&y);
ed[y].push_back(x);
if(vis[x]0){
cnt--;
vis[x]=1;
}
if(vis[y]0){
cnt--;
vis[y]=1;
}
}
if(cnt!=0){
cout<<0;
return 0;
}
for(int i=1;i<=n;++i){
sort(ed[i].begin(),ed[i].end());
head[i]=unique(ed[i].begin(),ed[i].end())-ed[i].begin();
}
for(int i=1;i<=n;i++){
if(sit[i]!=0)
continue;
memset(vis,0,sizeof(vis));
cnt=0;
dfs(i);
f=0;
if(cntn){
ans++;
sit[i]=1;
}else{
for(int i=1;i<=n;++i){
if(vis[i]==1){
sit[i]=2;
}
}
}
}
cout<<ans;
return 0;
}