POJ 2230 Watchcow && USACO Watchcow 2005 January Silver (欧拉回路)

题意:

  Bessie 最近做了农场看守,他每天晚上的工作就是巡视农场并且保证没有坏人破坏农场。从谷仓出发去巡视,并且最终回到谷仓。

  Bessie 视力不是很好,不能像其他农场的看守一样,对农场的每一条连接不同场地的路走一遍就可以发现是不是有异常情况,他需要每条路都走两遍,并且这两边必须是不同的方向,因为他觉得自己应该不会两次都忽略农场中的异常情况。

  每块地之间一定会由至少一条路相连。现在的任务就是帮他制定巡视路线。前提假设一定存在满足题意的路径。

输入:

  第一行输入两个数N(2 <= N <= 10000)和M(1 <= M <= 50000),表示农场一共有N块地M条路。

  第二到M+1行输入两个整数,表示对应的两块地之间有一条路。

输出:

  输出我2 * (m + 1)行,每行一个数字,表示Bessie 的巡查路径上地的编号,1号为谷仓,从1开始,从1结束。如果有多种你答案,输出任意一种。

样例输入

4 5

1 2

1 4

2 3

2 4

3 4

样例输出

1

2

3

4

2

1

4

3

2

4

1

解题思路:

  由于是无向边,而且每条边要求正反各走一次,所以一定存在欧拉回路。存图时把每条无向边看成两条相反的有向边,直接利用欧拉回路求解。

代码:

/*
POJ 2230 || USACO Watchcow 2005 January Silver
algs:链式前向星(存图) + 欧拉回路(找点)
time:2016/4/25
*/
/*
题目要求每条边走两次,且两个点之间至少有一条边,那么肯定有欧拉回路,存图是每条无向边保存两次.
*/
#include <stdio.h>
#include <string.h>
#include <iostream>
#include <math.h>
#include <queue>
#include <stack>
#include <algorithm>
using namespace std;  

int V,E;
const int maxV = 1e4;
const int maxE = 5e4;
int head[maxV + 7];
int visit[2 * maxE + 7];
stack<int> sna;
queue<int> ans;

struct EdgeNode
{
    int to;
    int next;
}edges[2 * maxE + 7];

void eulurDFS(int now)
{
    sna.push(now);//每次访问一个点就把这个点压入栈中。
    for(int i = head[now]; i != -1; i = edges[i].next)
    {
        if(visit[i]) continue;
        visit[i] = 1;
        eulurDFS( edges[i].to );
    }
    ans.push( sna.top() );//回溯时说明该点无临边,那么出栈,最后形成的就是欧拉回路的点的顺序
    sna.pop();
}

int main()
{
    //freopen("input.txt", "r", stdin);
    //freopen("output.txt", "w", stdout);
    scanf("%d%d", &V, &E);
    memset(head, -1, sizeof(head));
    for(int i = 1; i <= E; i++)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        edges[2 * i - 1].to = v;
        edges[2 * i - 1].next = head[u];
        head[u] = 2 * i - 1;

        edges[2 * i].to = u;
        edges[2 * i].next = head[v];
        head[v] = 2 * i;
    }
    memset(visit, 0, sizeof(visit));
    eulurDFS(1);
    while(!ans.empty())
    {
        printf("%d\n",ans.front());
        ans.pop();
    }
    return 0;
}
时间: 2024-10-23 02:33:28

POJ 2230 Watchcow && USACO Watchcow 2005 January Silver (欧拉回路)的相关文章

[欧拉回路] poj 2230 Watchcow

题目链接: http://poj.org/problem?id=2230 Watchcow Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 6055   Accepted: 2610   Special Judge Description Bessie's been appointed the new watch-cow for the farm. Every night, it's her job to walk acr

POJ 2230 Watchcow

Watchcow Time Limit: 3000ms Memory Limit: 65536KB This problem will be judged on PKU. Original ID: 223064-bit integer IO format: %lld      Java class name: Main Bessie's been appointed the new watch-cow for the farm. Every night, it's her job to walk

[2016-01-27][POJ][2230][Watchcow]

H - 欧拉图 中级者向 Time Limit:3000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Practice POJ 2230 Description Bessie's been appointed the new watch-cow for the farm. Every night, it's her job to walk across the farm and make s

POJ 2230 Watchcow 欧拉回路题解

本题就是以每个节点和节点之间建路,而且说明是无向图,不过这里有个技巧,就是根据题意把它当成有向图来做,就成了直接查找有向图的欧拉回路就可以了.因为题意是需要每条边都走两遍的,而且每次走的方向相反. 观察出这点,那么这道题就好做啦,直接建图,Feury递归求解就可以了. 建图注意需要建邻接表,不要建矩阵,因为建成矩阵,那么会很大很大,而根据题意,建成邻接表最多只需要5倍的顶点数. 打印的顺序是逆过来打和顺着打都可以的,因为先走那边都可以. #include <stdio.h> #include

POJ 2230 Watchcow (欧拉回路)

题目地址:POJ 2230 最普通的欧拉回路.边不重复记录点.不多说. 代码如下: #include <iostream> #include <string.h> #include <math.h> #include <queue> #include <algorithm> #include <stdlib.h> #include <map> #include <set> #include <stdio.

POJ 2230 解题报告

分析: 基础的欧拉路算法,变化在于要求每条边正向和反向各走一遍. 链式前向星构图,只要标记走过的单向边,边找边输出即可. code #include <iostream> #include <cstdio> using namespace std; struct node { int v, ne; } edge[100009]; int head[10009], vis[100009], cnt = 1; int n, m, x, y; void addedge (int u, i

POJ 1041 John&#39;s trip 无向图的【欧拉回路】路径输出

欧拉回路第一题TVT 本题的一个小技巧在于: [建立一个存放点与边关系的邻接矩阵] 1.先判断是否存在欧拉路径 无向图: 欧拉回路:连通 + 所有定点的度为偶数 欧拉路径:连通 + 除源点和终点外都为偶数 有向图: 欧拉回路:连通 + 所有点的入度 == 出度 欧拉路径:连通 + 源点 出度-入度=1 && 终点 入度 - 出度 = 1 && 其余点 入度 == 出度: 2.求欧拉路径 : step 1:选取起点(如果是点的度数全为偶数任意点为S如果有两个点的度数位奇数取一

HDU 1116 || POJ 1386 || ZOJ 2016 Play on Words (欧拉回路+并查集)

题目链接 题意 : 有很多门,每个门上有很多磁盘,每个盘上一个单词,必须重新排列磁盘使得每个单词的第一个字母与前一个单词的最后一个字母相同.给你一组单词问能不能排成上述形式. 思路 :把每个单词看成有首字母指向尾字母的有向边,每个字母看成一个点,题中要求等效于判断图中是否存在一条路径经过每一条一次且仅一次,就是有向欧拉通路.统计个顶点的出入度,如果每个点的出入度都相同,那就是欧拉回路,如果有两个奇数度,那就是欧拉通路,除此之外,都不能满足要求.还有别忘了判断是否连通,此时用到并查集,图中所有的边

poj 3279 Filptile (USACO 2007 Open Silver)

题意: n*m块区域,每一块有正反两面,两面分别是白色和黑色. 翻转一块区域的同时, 与其相邻的四块区域也会同时被反转 问最少需要翻转的次数 ,使所有的区域都变成白色 输出其翻转方案 思路: 枚举第一行的翻转状态 如果已经知道了第一行的状态,那么后面几行的状态就随之确定了--(如果该区域的上面一个区域是黑色,那这个区域必然是要反转才能让他上面的区域变成白色) 然后比较和记录最少的翻转次数 输出即可 code: #include<cstdio> #include<cstring> #