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; }