您的位置:首页 > 其它

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

2016-04-16 15:02 411 查看
本文链接:http://www.cnblogs.com/Ash-ly/p/5398425.html

[b]题意:[/b]

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

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

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

[b]输入:[/b]

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

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

[b]输出:[/b]

  输出我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

[b]解题思路:[/b]

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

[b]代码:[/b]

/*
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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: