这题按照江老师告诉我们探索题目的方法,我就列举了一些不能上车的一些例子:
1 2 1 3 2 4 4 3 -1 |
![爆炸化合物(explosion) - 周正华 - 周正华的博客 爆炸化合物(explosion) - 周正华 - 周正华的博客](http://img2.ph.126.net/25xf2BaCSQC0isOAKg508w==/6630714822467496665.png)
4 6 3 4 2 3 1 4 2 5 6 5 -1 |
结果是这样子:
于是就发现,似乎能组成爆炸化合物的,必定是有环形的。
又通过几组数据验证得到,这个发现是正确的。
接下来就简单了,因为之前做过tree,现在做判断环形的题目就比较容易。
参考程序:
#include <iostream> #include <fstream> using namespace std; int fa[1000001],line[1000001],point[1000001]; //还不知道数据范围,所以先搞这么多 int u_f(int x) //并查集找根并压缩路径 { int root=x; while(fa[root]!=root) root=fa[root]; while(fa[x]!=x) { int y=fa[x]; fa[x]=root; x=y; } return root;
} int main() { freopen("explosion.in","r",stdin); freopen("explosion.out","w",stdout); int ans=0;
//把 i 的父节点指向自己,并初始化边数与点数 for(int i=0;i<=100000;i++) { fa[i]=i; line[i]=0; point[i]=1; } while(1) { int x,y; scanf("%d",&x); //这里就是怕数据较大时cin会超时 if(x==-1) break; //如果结束(-1)则退出循环 scanf("%d",&y); int fx=u_f(x); int fy=u_f(y); if(fx==fy) //如果为环形,边数加 1 line[fx]++; else //若不是,则连接两个节点,并且把边数与点数也随之改变 { fa[fy]=fx; line[fx]+=line[fy]+1; point[fx]+=point[fy]; } if(point[fx]-line[fx]!=1) //如果这个连通块不是一棵树(即为环形),累加器累加 { ans++; line[fx]--; //因为并没有把它放上飞机,所以边数也要变回来 } } printf("%d",ans);
return 0; }
|