CF238_DIV1_C
来源:互联网 发布:ubuntu查看硬盘总大小 编辑:程序博客网 时间:2024/05/29 11:12
题意是给一个无重边无自环的连通无向图,每次取出两条有公共点的边,求一种取边方案。无解时输出no solution。
很容易想,无解等价于边数为奇数。有解的时候靠构造。构造是一个猜想+调整的过程。
可以肯定的是,要对边遍历一遍。但是如果先匹配父亲的边再匹配儿子的边的话,可能会造成把原图分裂成两个子图并且有个子图边数为奇数进而导致无解的情况。
所以想到先匹配儿子的边,这样,父亲的边可以适时调整。需要注意的是,虽然是按边遍历,但是不能由儿子访问父亲,因为这样会输出重边。
#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <cmath>#include <queue>#include <vector>#include <stack>#define clr(A) memset(A,0,sizeof(A))#define mm 100005using namespace std;typedef long long LL;typedef pair<int, int > P;vector<P> by[mm];int ans[mm][3],c = 0;vector<int> E[mm];int vis[mm],used[mm];int n,m;int dfs(int pre,int cur){ used[cur] = 1; for(int i = 0; i < by[cur].size();i++) { int u = by[cur][i].first, d = by[cur][i].second; if(vis[d]||used[u]) continue; //边不能重复访问,不能访问祖先 vis[d] = 1; // printf("edge = %d %d\n",cur,u); if(dfs(cur,u)) E[cur].push_back(u); } used[cur] = 0; int i; for(i = 0; i+1<E[cur].size();i+=2) { ans[c][0] = E[cur][i]; ans[c][1] = cur; ans[c][2] = E[cur][i+1]; c++; } if(i<E[cur].size()) { ans[c][0] = pre;ans[c][1] = cur;ans[c++][2] = E[cur][i]; E[cur].clear();return 0; } else {E[cur].clear();return 1;} //E[cur]要清空一下,因为cur可能会再次被遍历,但E[cur]中的边已经用过。}int main(){ freopen("CF.in","r",stdin); scanf("%d%d",&n,&m); if(m & 1) {printf("No solution\n");return 0;} for(int i =1; i<=n;i++) if(!by[i].empty()) by[i].clear(); for(int i =1; i<=n;i++) if(!E[i].empty()) E[i].clear(); for(int i = m;i>=1;i--) { int a,b; scanf("%d%d",&a,&b); by[a].push_back(P(b,i)); by[b].push_back(P(a,i)); } clr(vis); dfs(-1,1); for(int i = 0;i<c;i++) printf("%d %d %d\n",ans[i][0],ans[i][1],ans[i][2]); return 0;}
0 0
- CF238_DIV1_C
- PHP 预览PDF时一种错误情况的解决
- linux下定时ping一段IP地址 如果ping不通则执行
- 对话框中添加工具条
- 针对Java中i++的一个例题
- android cavas 绘制坐标系并显示矩形波方波-横轴为当前时间动态更新(不用achartengine)
- CF238_DIV1_C
- hdu4535
- 黑马程序员---集合框架【List接口和ListIterator接口】、
- hadoop学习路线(转)
- C# 调用 CMD
- 黑马程序员——Java学习笔记之①——“Java编程基础”
- 关于 jdk javasoft注册表问题
- Ubuntu 12.04下NFS安装配置图解
- 英语中常见从句的简化