bzoj1854 [Scoi2010]游戏(并查集)

来源:互联网 发布:怎样收藏淘宝店铺 编辑:程序博客网 时间:2024/06/05 17:32

将每个武器变成一条边 连接两个属性
如果一个联通块形成了一棵n个点的树 那么只能满足其中的n-1个的点
如果一个联通块有一个环 那么就能满足所有的点.因此我们用并查集来维护一下,还需要记录有没有环。合并的时候保证一定以最大的为根。则无环时只有根不能取到,有环时都能取到。最后从1往后扫,看到哪以后取不到了。

#include<cstdio>#include<iostream>#include<cstring>using namespace std;int const N=10005;int n,fa[N];bool vis[N];int find(int x){    return fa[x]==x?x:fa[x]=find(fa[x]);}void merge(int xx,int yy){    if(xx>yy) swap(xx,yy);    if(vis[xx]) vis[yy]=1;//xx有环,合并后也有环,最大的yy也可以达到     fa[xx]=yy; vis[xx]=1;//小的可以打到,大的目前不行 }int main(){//  freopen("a.in","r",stdin);    scanf("%d",&n);    memset(vis,0,sizeof(vis));    for(int i=1;i<=10000;++i) fa[i]=i;    for(int i=1;i<=n;++i){        int x,y;        scanf("%d%d",&x,&y);        int xx=find(x),yy=find(y);        if(xx==yy) vis[xx]=1;//有环,根是最大的,也可以达到         else merge(xx,yy);    }    for(int i=1;i<=n+1;++i)//有可能都能打到。         if(!vis[i]){            printf("%d",i-1);return 0;        }}