哈理工 校赛(热身赛)2238 围巾的纠结(判断回路问题)
2015-05-25 16:37
211 查看
围巾的纠结 | ||||||
| ||||||
Description | ||||||
小破想要织一条围巾,可是她并不擅长于织围巾。由于工作太忙,每天她都只能织一点。为了快速的织完围巾,她决定直接把毛线球连在一起。围巾上有球球还是非常可爱的嘛~ 于是小破去商店买了n个毛线球。每天晚上睡觉之前,她就抽出一点时间,把其中两个原本分开的毛线球织在一起。由于是睡觉之前干活,人太困了,过了m天之后,她发现自己完全织乱了,于是她决定拆掉重织。可是由于她的织法过于特殊,她发现,一旦几个毛线球被织成了一个圈,就不能完好的解开了。现在她想知道,她还能把这条"围巾"还原吗? | ||||||
Input | ||||||
多组测试数据 每组测试数据第一行有两个整数n,m(1 <= n <= 10000, 1 <= m <= 1000000) 接下来有m行,每行有两个数a,b,表示将a和b号毛球织到一起。 | ||||||
Output | ||||||
对于每组测试数据,如果她能还原,则输出"YES", 否则输出"NO" | ||||||
Sample Input | ||||||
5 4 1 2 2 3 3 1 1 4 5 4 1 2 2 3 3 4 4 5 | ||||||
Sample Output | ||||||
NO YES | ||||||
Source | ||||||
哈尔滨理工大学第五届ACM程序设计竞赛(热身) |
先来看看这种超时的经典算法:
按照算法描述写出来也是不容易啊。
#include<iostream> #include<string.h> #include<set> #include<queue> using namespace std; const int M=10010; int graph[M][M]; int digree[M]; int main() { int n,m; while(cin>>n>>m,n+m) { memset(graph,0,sizeof(graph)); memset(digree,0,sizeof(digree)); for(int i=1; i<=m; i++) { int a,b; cin>>a>>b; if(!graph[a]&&!graph[b][a])//防止有重边,导致各定点度数变大。 { graph[a][b]=1;添加双向边 graph[b][a]=1; digree[b]++; digree[a]++; } } queue<int>q; set<int>dict; for(int j=1; j<=n; j++) { if(digree[j]==0||digree[j]==1)//因为图的子图是一个回路,那么每个顶点度数大于等于2,所以删除读数为0和1的结点 { q.push(j); } } while(!q.empty()) { int cur=q.front(); dict.insert(cur); q.pop(); for(int k=1; k<=n; k++) { if(graph[cur][k]) { graph[k][cur]=0;//删除这个结点和所在的边 graph[cur][k]=0; digree[k]--; //同时相连的结点度数减1 if(digree[k]==0||digree[k]==1)//判断是否这个顶点可以删除 q.push(k); } } } if(dict.size()!=n) //如果每个顶点都进入过队列,则说明可以全部删除,反之则反,另外不能用count记录撤出队列元素个数 cout<<"NO"<<endl;//来判断(!); else cout<<"YES"<<endl; } return 0; } /* 5 5 2 1 1 2 2 3 3 4 4 5 */
[b]如果使用并查集原理,每次往图中加入一条边之前判断两个短点是否属于不同的连通块儿,如果是,那么可以合并,否则必然存在回路。
#include<iostream> #include<string.h> using namespace std; const int M=50001; int F[M]; int Find(int x) { if(x!=F[x]) return F[x]=Find(F[x]); } bool Is_same(int x,int y) { return Find(x)==Find(y); } void union_set(int x , int y) { int tx=Find(x); int ty=Find(y); if(tx!=ty) { F[tx]=ty; } } int main() { int n,m; while(cin>>n>>m) { int flag=0; for(int j=0;j<M;j++) F[j]=j; for(int i=0;i<m;i++) { int a,b; cin>>a>>b; if(Is_same(a,b)) flag=1; union_set(a,b); } if(flag) cout<<"NO"<<endl; else cout<<"YES"<<endl; } return 0; }
相关文章推荐
- 哈理工OJ 2238—围巾的纠结(并查集判环)
- 哈理工oj hrbust 2238 围巾的纠结【并查集】
- 并查集判断图有无回路问题之hdu1272
- 纠结的输入 回车判断格式问题
- 围巾的纠结(并查集之非完整集合的子集合是否连成圈的问题)
- 我纠结的sql返回受影响行数与判断是否成功的问题
- 我纠结的sql返回受影响行数与判断是否成功的问题
- 机房收费系统总结之4——VB.NET 轻松解决判断文本框、组合框为空问题
- hibernate+struts2登录 用户名 密码 判断问题
- 遵循以下几条原则,不再纠结Xcode代码签名问题
- mybatis 传参为 Integer 时 ,Mapper 文件 中判断 条件 问题,传入0值,直接忽略判断
- POJ 1703 Find them, Catch them 并查集 (关系问题 判断是否在一个集合)
- C51程序unsigned和signed类型数据判断时候需要注意的问题
- jQuery中checkbox的click方法中判断checked属性问题
- c:if,c:choose解决jsp判断问题
- javascript判断下拉菜单值的问题
- 关于ios设备的旋转判断问题
- 判断单链表是否存在环,判断两个链表是否相交问题详解
- 如何判断一个图中是否存在回路