POJ 1041 John's trip(欧拉回路)
2015-09-02 19:03
393 查看
题意:给出两个点所构成的一条边 点和边各有各的计数规则,已知所给的图是连通图,求能否从起点出发,每条边经过切只经过一次再次回到原点,若不能输出错误信息,若能输出可能存在的路径的最小字典序。
解题思路:
题目已经明确所给的图是连通图,所以不用在判断图的连通性了。先判断是否存在欧拉回路,若有度数为奇数的点则不存在。可以使用链式向前星存图,边的编号可以想象成类似于权值,要求输出的字典序最小,所以在dfs尝试回溯构建欧拉回路的时候,应该优先尝试权值小的点,所以要对读入的关系,先进行排序。最后判断就好了。
模板:
比较悲哀的是,算法的思路很正确, 有一点细节没处理好, 导致WA了几次。
WA的dfs代码:警示自己
最后的AC代码
解题思路:
题目已经明确所给的图是连通图,所以不用在判断图的连通性了。先判断是否存在欧拉回路,若有度数为奇数的点则不存在。可以使用链式向前星存图,边的编号可以想象成类似于权值,要求输出的字典序最小,所以在dfs尝试回溯构建欧拉回路的时候,应该优先尝试权值小的点,所以要对读入的关系,先进行排序。最后判断就好了。
模板:
void dfs(int now) { for(int k = head[now] ; k != -1 ; k = edge[k].next) { if(!vis[k]) { vis[k] = true; vis[k^1] = true; dfs(edge[k].to); ans[iq++] = k; } } }
比较悲哀的是,算法的思路很正确, 有一点细节没处理好, 导致WA了几次。
WA的dfs代码:警示自己
void dfs(int now) { for(int k = head[now] ; k != -1 ; k = edge[k].next) { if(!vis[k]) { vis[k] = true; vis[k^1] = true; dfs(edge[k].to); ans[iq++] = edge[k].way; } } }
最后的AC代码
Memory: 840 KB | Time: 32 MS | |
Language: G++ | Result: Accepted |
#include<algorithm> #include<cstdio> #include<cstdlib> #include<cstring> #include<cmath> #include<cctype> #include<list> #include<iostream> #include<map> #include<queue> #include<set> #include<stack> #include<vector> using namespace std; #define FOR(i, s, t) for(int i = (s) ; i <= (t) ; ++i) #define REP(i, n) for(int i = 0 ; i < (n) ; ++i) int buf[10]; inline long long read() { long long x=0,f=1; char ch=getchar(); while(ch<'0'||ch>'9') { if(ch=='-')f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') { x=x*10+ch-'0'; ch=getchar(); } return x*f; } inline void writenum(int i) { int p = 0; if(i == 0) p++; else while(i) { buf[p++] = i % 10; i /= 10; } for(int j = p - 1 ; j >= 0 ; --j) putchar('0' + buf[j]); } /**************************************************************/ #define MAX_N 2005 const int INF = 0x3f3f3f3f; bool vis[MAX_N]; int degree[MAX_N]; int cnt = 0; int head[MAX_N]; struct node { int to, next, way; } edge[MAX_N << 2]; struct node2 { int u, v, w; } a[MAX_N << 1]; int top = 0; int iq = 0; int ans[MAX_N]; inline void init() { memset(head, -1, sizeof(head)); memset(vis, false, sizeof(vis)); memset(degree, 0, sizeof(degree)); memset(ans, 0 ,sizeof(ans)); memset(a, 0, sizeof(a)); iq = 0; top = 0; cnt = 0; } void add_edge(int u, int v, int w) { edge[top].to = v; edge[top].way = w; edge[top].next = head[u]; head[u] = top++; } void dfs(int now) { for(int k = head[now] ; k != -1 ; k = edge[k].next) { int v = edge[k].to; if(!vis[edge[k].way]) { vis[edge[k].way] = true; //vis[edge[k].way] = true; dfs(v); ans[iq++] = edge[k].way; } } } bool cmp(node2 a, node2 b) { return a.w < b.w; } int main() { int u, v, w; while(scanf("%d%d", &u, &v)&&(u + v)) { init(); // int cnt = 0; // int tot = 0; scanf("%d", &w); a[cnt].u = u; a[cnt].v = v; a[cnt].w = w; cnt++; int home = min(u, v); while(scanf("%d%d", &u, &v) && (u + v)) { scanf("%d", &w); a[cnt].u = u; a[cnt].v = v; a[cnt].w = w; cnt++; } sort(a, a + cnt, cmp); // for(int i = 0 ; i < cnt ; i++) // { // cout<<a[i].u<<" "<<a[i].v<<" "<<a[i].w<<endl; // } for(int i = 0 ; i < cnt ; i++) { add_edge(a[i].u, a[i].v, a[i].w); add_edge(a[i].v, a[i].u, a[i].w); degree[a[i].u]++; degree[a[i].v]++; } int flag = 0; for(int i = 0 ; i < 50 ; i++) { if(degree[i] % 2) { flag = 1; break; } } if(flag) { printf("Round trip does not exist.\n"); continue; } dfs(home); for(int i = 0 ; i < iq ; i++) { cout<<ans[i]<<" "; } cout<<endl; } return 0; }
相关文章推荐
- Linux Vim,Find使用方法以及磁盘与文件系统管理
- POJ3154 Graveyard(和刘汝佳的算法不一样哦)
- window service 创建
- 反射
- 黑马程序员之IO流2
- 归并排序&求逆序数
- 人与人的压迫
- 算法:归并排序
- poj-1743 Musical Theme
- ls命令
- Win10文件管理器那些你不知道的秘密
- java工具类之Graphics
- 浅析回调函数和Schedule
- C++primer 阅读笔记-模板与泛型编程(成员模板)
- 上下级关系
- uvaoj 11174 - Stand in a Line
- 哲学家总是用不同的方式解释世界,问题在于改变世界。 ---- 卡尔.马克斯
- 反射心得
- POJ题目 1151|| HDOJ 题目1542Atlantis(线段树+离散化+扫描线)
- Unity3d获取IOS设备唯一标识,以及IDFA