bzoj 1854

最大匹配,但算时间复杂度是过不去的。

#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;
const int maxv=10001,maxn=1000001,maxe=2000001;
int read(){
    char c; while(!isdigit(c=getchar())); int x=c-'0';
    while(isdigit(c=getchar())) x=x*10+c-'0'; return x;
}
int cnt,hed[maxv],nex[maxe],lnk[maxe];
void add(int u,int v){
    nex[++cnt]=hed[u];
    lnk[hed[u]=cnt]=v;
}
int vis[maxn],cos[maxn];
bool find(int o,int t){
    for(int i=hed[o];i;i=nex[i])
        if(vis[lnk[i]]!=t){
            vis[lnk[i]]=t;
            if(!cos[lnk[i]] || find(cos[lnk[i]],t)) return cos[lnk[i]]=o,1;
        }
    return 0;
}
int main(){
    int n=read();
    for(int i=1;i<=n;i+=1){
        int u=read(),v=read();
        add(u,i); add(v,i);
    }
    for(int i=1;i<maxv;i+=1)
        if(!find(i,i)) return printf("%d",i-1),0;
    printf("%d",maxv-1);
    return 0;
}

并查集加贪心。

贪心,两个数所在集合的根都没选我们就选小的。

如果有一个选了,那么就选另一个。

如果两个数在同一集合,那么说明出现了环,所在集合所有数都可以选了,于是把根赋值为可选。

注意根是所在集合中的最大值。

#include<cstdio>
#include<cctype>
#include<algorithm>
using namespace std;
const int maxv=10001;
int read(){
    char c; while(!isdigit(c=getchar())); int x=c-'0';
    while(isdigit(c=getchar())) x=x*10+c-'0'; return x;
}
int fa[maxv],ye[maxv];
int find(int x){return x==fa[x]? x:fa[x]=find(fa[x]);}
void merge(int u,int v){
    if(u>v) swap(u,v);
    if(!ye[u]) ye[u]=1; else ye[v]=1;
    fa[u]=v;
}
int main(){
    int n=read();
    for(int i=1;i<maxv;i+=1) fa[i]=i;
    for(int i=1;i<=n;i+=1)
        merge(find(read()),find(read()));
    for(int i=1;i<maxv;i+=1)
        if(!ye[i]) return printf("%d",i-1),0;
    printf("%d",maxv-1);
    return 0;
}

 

posted @ 2017-10-24 10:36  或是七一  阅读(81)  评论(0编辑  收藏  举报