P2341 [USACO03FALL][HAOI2006]受欢迎的牛 G

Archie

显然做法就是建反图,每个点都遍历一下,然后​能过

然而有几个点死能卡常数,怎么办呢

干他

如果一头牛不能到达所有奶牛,它能到的所有牛都不行,同理,如果一头奶牛可以,它能到的所有牛都行

然而,这么干还是会被最后一个点干掉。

采用vector,对于每一个点的出边从小到大排序,因为最后枚举是从从小到大的,显然这么干更容易让上优化起效

就干过去了

include

include

include

include

using namespace std;
int n,m;
int vis[10005];
vector ed[10005];
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(cnt
n){
ans++;
sit[i]=1;
}else{
for(int i=1;i<=n;++i){
if(vis[i]==1){
sit[i]=2;
}
}
}
}
cout<<ans;
return 0;
}

posted @ 2021-07-17 20:27  Simex  阅读(56)  评论(0编辑  收藏  举报