bzoj1854: [Scoi2010]游戏
经典好题,居然是并查集。
把属性作为点,武器看作边,连接它的两个属性,让属性大的做父亲。
对于一个联通块,若他不成环,那么就应该有n-1种方案,成环就有n种。(n为最长链)
判断的方法是每次合并的时候,若已经是同一联通块中,那么情况就一定有作为这个联通块的根的值,若不在,那就合并,同时到达较小那个根也是必定的,由于n小所以v[i]表示i能否达到,最后判就行。
#include<cstdio> #include<iostream> #include<cstring> #include<cstdlib> #include<algorithm> #include<cmath> using namespace std; int fa[1100000]; int findfa(int x) { if(fa[x]==x)return x; fa[x]=findfa(fa[x]);return fa[x]; } bool v[11000]; int main() { int n; scanf("%d",&n); for(int i=1;i<=10000;i++)fa[i]=i; int x,y; memset(v,false,sizeof(v)); for(int i=1;i<=n;i++) { scanf("%d%d",&x,&y); int fx=findfa(x),fy=findfa(y); if(fx!=fy) { if(fx>fy)swap(fx,fy); fa[fx]=fy; } v[fx]=true; } for(int i=1;i<=10000+1;i++) if(v[i]==0){printf("%d\n",i-1);break;} return 0; }
pain and happy in the cruel world.