之所以把这两题放一块看是因为寻找祖先结点是有区别的,不然一个爆栈,一个TLE
hdu1272 小希的迷宫
#include<iostream> #include<cstring> #include<cstdio> using namespace std; int root[100001],foot[100001]; int find(int t){ //不能用递归寻找祖先借点,不然会爆栈,汗 while(root[t]!=t) t=root[t]; return root[t]; } void check(int a,int b){ foot[a]=foot[b]=1; int ra=find(a); int rb=find(b); if(ra!=rb) root[ra]=rb; } void reset(){ //初始化 for(int i=1;i<=100000;i++) root[i]=i; memset(foot,0,sizeof(foot)); } int main(){ int i=1; bool flag=0; int a,b; int key=0; reset(); while(scanf("%d%d",&a,&b)){ //输入的格式也很奇葩 if(a==-1&&b==-1) break; if(a==0&&b==0){ for(i=1;i<=100000;i++) if(root[i]==i&&foot[i]==1) //foot[]==1代表输入文件中包含的点 key++; if(key>1) flag=1; if(flag) printf("No\n"); else printf("Yes\n"); flag=0; key=0; reset(); continue; } if(find(a)==find(b)) flag=1; else check(a,b); } return 0; }
hdu1856 More is better
#include<iostream> #include<cstdio> #include<cstring> using namespace std; int root[10000010],sign[10000010]; int find(int c){ //亲测若采用while()找祖先直接TLE if(root[c]!=c) root[c]=find(root[c]); return root[c]; } void check(int a,int b){ int ra=find(a); int rb=find(b); if(ra!=rb){ root[ra]=rb; sign[rb]+=sign[ra]; } } int main(){ int m; int i; int b1,b2; while(scanf("%d",&m)!=EOF){ for(i=1;i<=10000000;i++){ root[i]=i; sign[i]=1; } for(i=1;i<=m;i++){ scanf("%d%d",&b1,&b2); check(b1,b2); } int ans=0; for(i=1;i<=10000000;i++) if(sign[i]>ans) ans=sign[i]; printf("%d\n",ans); } return 0; }
我已经感觉到蛋疼了...