加载中…
个人资料
  • 博客等级:
  • 博客积分:
  • 博客访问:
  • 关注人气:
  • 获赠金笔:0支
  • 赠出金笔:0支
  • 荣誉徽章:
正文 字体大小:

POJ PKU 2230 图论 欧拉图遍历

(2010-08-10 09:21:02)
标签:

poj

pku

2230

图论

欧拉图

it

分类: 图论

题目描述:

给你一个有向欧拉图,让你输出任意一种合法的便利。

解题报告:

深搜即可,注意是后序深搜,即每个节点的边要在搜完之后才输出。

证明:转自http://gisyhy.blog.163.com/blog/static/12939034320102181045134/

其实我们不能死瞄着dfs一直深搜,这样就很难想通了,我们可以想想,欧拉图的节点的度的问题,(我这里就专门讨论有向图,无向图可以转换成有向图做的),假设节点s为起点,则深搜到不能搜的时候那个节点就是s。为什么呢,只要将这点想通,基本就没什么问题了。

我们知道如果一个节点入度减1,那么它的出度必然要减1,在以s为起点的路径中,se1v1e2v2....eivi,如果vi节点

不是s节点且为深搜的最后节点,也就是说vi没有了出度,然而我们知道对于v1...v(i-1)节点入度一但减少,出度也就减少了,然而对于s起点来说只要出度减少却没有入度减少,vi的入度减少却没有了出度,所以证明vi节点不可能会成为不是s节点且为深搜的最后节点,即除非他还不是深搜的最后节点,到这里我们基本就可以确定了,vi要满足深搜最后节点必然为vi==s,这样的话vi的入度减少了,出度也减少了(因为s出度减少了),s的出度减少了,入度也减少了(因为vi的入度减少了)所以可以证明以s为起点的深搜最后节点也为s。

哎呀,说的有点累了,不知道大家明白没。

然后就是返回了,当沿着路径返回的途中如果vi节点还有出度的话,那么就以vi为起点开始深搜,根据上面的证明,我们可以知道最后的深搜节点肯定为vi起点了。

现在大概知道我要最后说什么了吧,将回路se1v1e2v2.....eivi(ei1vi1ei2vi2...eiivi)e(i+1).....ejs,括号里面的就是返回途中发生的又一次回路咯,把它嵌入到里面自然大的回路也满足要求了。

代码如下:

#include<iostream>
#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
int n, m, v[10001], cnt, id[10001];
struct edge{int to, next; bool vst;} e[110000];
void insert(int from, int to){e[cnt].to = to, e[cnt].next = v[from], e[cnt].vst = 0; v[from] = cnt++;}
void dfs(int i)
{
    printf("%d\n", i);
    while(id[i] != -1)
    {
        if (!e[id[i]].vst)
        {
            e[id[i]].vst = 1;
            dfs(e[id[i]].to);
        }
        id[i] = e[id[i]].next;
    }

}
int main()
{
    while(scanf("%d%d", &n, &m) != EOF)
    {
        memset(v, -1, sizeof(int) * (n + 1)); cnt = 0;
        for(int i = 0; i < m; i++)
        {
            int a, b;scanf("%d%d", &a, &b);
            insert(a, b), insert(b, a);
        }
        for(int i = 1; i <= n; i++) id[i] = v[i];
        dfs(1);
    }
    return 0;
}

0

阅读 收藏 喜欢 打印举报/Report
  

新浪BLOG意见反馈留言板 欢迎批评指正

新浪简介 | About Sina | 广告服务 | 联系我们 | 招聘信息 | 网站律师 | SINA English | 产品答疑

新浪公司 版权所有