hihocoder 1181 欧拉路.二

传送门:欧拉路·二

#1181 : 欧拉路·二

时间限制:10000ms

单点时限:1000ms

内存限制:256MB

描述

在上一回中小Hi和小Ho控制着主角收集了分散在各个木桥上的道具,这些道具其实是一块一块骨牌。主角继续往前走,面前出现了一座石桥,石桥的尽头有一道火焰墙,似乎无法通过。小Hi注意到在桥头有一张小纸片,于是控制主角捡起了这张纸片,只见上面写着:

将M块骨牌首尾相连放置于石桥的凹糟中,即可关闭火焰墙。切记骨牌需要数字相同才能连接。
——By 无名的冒险者

小Hi和小Ho打开了主角的道具栏,发现主角恰好拥有M快骨牌。小Ho:也就是说要把所有骨牌都放在凹槽中才能关闭火焰墙,数字相同是什么意思?小Hi:你看,每一块骨牌两端各有一个数字,大概是只有当数字相同时才可以相连放置,比如:小Ho:原来如此,那么我们先看看能不能把所有的骨牌连接起来吧。 提示:Fleury算法求欧拉路径

输入

第1行:2个正整数,N,M。分别表示骨牌上出现的最大数字和骨牌数量。1≤N≤1,000,1≤M≤5,000第2..M+1行:每行2个整数,u,v。第i+1行表示第i块骨牌两端的数字(u,v),1≤u,v≤N

输出

第1行:m+1个数字,表示骨牌首尾相连后的数字比如骨牌连接的状态为(1,5)(5,3)(3,2)(2,4)(4,3),则输出"1 5 3 2 4 3"你可以输出任意一组合法的解。

样例输入
5 5
3 5
3 2
4 2
3 4
5 1
样例输出

1 5 3 4 2 3

这道题的要点是如何实现删边,对一种用数组实现的临接表(可以取代vector<int>)稍加修改便可。

 1 struct edge{
 2   int to, prev, next;
 3 };
 4 edge E[MAX_E<<1]; //error-prone
 5 int path[MAX_E<<1];
 6 int pos[MAX_V], size[MAX_V];
 7 int path_size;
 8 void add_edge(int &id, int u, int v){
 9   E[id].to=v;
10   E[pos[u]].next=id;
11   E[id].prev=pos[u];
12   E[id].next=-1;
13   pos[u]=id++;
14   size[u]++;
15 }
16 void get_graph(int E){
17   int id=0;
18   int u, v;
19   while(E--){
20     scanf("%d%d", &u, &v);
21     add_edge(id, u, v);
22     add_edge(id, v, u);
23   }
24 }
25 void move_edge(int u, int now){
26   int &pre=E[now].prev;
27   if(~pre){
28     E[pre].next=E[now].next;
29   }
30   int &nt=E[now].next;
31   if(~nt){
32     E[nt].prev=E[now].prev;
33   }
34   else{
35     pos[u]=E[now].prev;
36   }
37 }

我们看到实现删边只需增加一个next域(domain)。

注意:上面代码中的get_graph函数中应当包含如下的初始化

memset(pos, -1, sizeof(pos));
memset(size, 0, sizeof(size));

我写在main()中了,这是不可缺少的。

完整代码:

 1 #include<bits/stdc++.h>
 2 #define set1(a) memset(a, -1, sizeof(a))
 3 #define set0(a) memset(a, 0, sizeof(a))
 4 using namespace std;
 5 const int MAX_V=1e3+10, MAX_E=5e3+10;
 6 struct edge{
 7   int to, prev, next;
 8 };
 9 edge E[MAX_E<<1]; //error-prone
10 int path[MAX_E<<1];
11 int pos[MAX_V], size[MAX_V];
12 int path_size;
13 void add_edge(int &id, int u, int v){
14   E[id].to=v;
15   E[pos[u]].next=id;
16   E[id].prev=pos[u];
17   E[id].next=-1;
18   pos[u]=id++;
19   size[u]++;
20 }
21
22 void get_graph(int E){
23   int id=0;
24   int u, v;
25   while(E--){
26     scanf("%d%d", &u, &v);
27     add_edge(id, u, v);
28     add_edge(id, v, u);
29   }
30 }
31 void move_edge(int u, int now){
32   int &pre=E[now].prev;
33   if(~pre){
34     E[pre].next=E[now].next;
35   }
36   int &nt=E[now].next;
37   if(~nt){
38     E[nt].prev=E[now].prev;
39   }
40   else{
41     pos[u]=E[now].prev;
42   }
43 }
44 void dfs(int u){
45   int now;
46   while(now=pos[u], ~now){ //error-prone
47     int &v=E[now].to;
48     move_edge(u, now);
49     move_edge(v, now^1);
50     dfs(v);
51   }
52   path[path_size++]=u;
53 }
54 int main(){
55   freopen("in", "r", stdin);
56   int V, E;
57   scanf("%d%d", &V, &E);
58   set1(pos);
59   set0(size);
60   get_graph(E);
61   path_size=0;
62   int beg=1;
63   for(int i=1; i<=V; i++){
64     if(size[i]&1){
65       beg=i;
66       break;
67     }
68   }
69   dfs(beg);
70   for(int i=0; i<path_size; i++){
71     printf("%d ", path[i]);
72   }
73   puts("");
74   return 0;
75 }

请特别注意第48、49行是如何删边的。我们看到这种用数组实现的临界表是比较灵活与实用的。

时间: 2024-10-05 07:52:27

hihocoder 1181 欧拉路.二的相关文章

hihoCoder - 1181 - 欧拉路&#183;二 (Fleury算法求欧拉路径)

#1181 : 欧拉路·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上一回中小Hi和小Ho控制着主角收集了分散在各个木桥上的道具,这些道具其实是一块一块骨牌. 主角继续往前走,面前出现了一座石桥,石桥的尽头有一道火焰墙,似乎无法通过. 小Hi注意到在桥头有一张小纸片,于是控制主角捡起了这张纸片,只见上面写着: 将M块骨牌首尾相连放置于石桥的凹糟中,即可关闭火焰墙.切记骨牌需要数字相同才能连接. --By 无名的冒险者 小Hi和小Ho打开了主角的道具栏,发现

hihoCoder #1181: 欧拉路&#183;二 (麻烦)

题意:提供一个图,要求找出欧拉路的路径(任意合法的路径均可,保证图肯定有欧拉路). 思路:深搜的过程中删除遍历过的边,并在回溯时打印出来.在深搜时会形成多个环路,每个环都有一个或多个结点与其他环相扣,这样就可以产生欧拉路. 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N=1005; 4 int n, m, a, b; 5 vector< vector<int> > vect;//邻接表 6

[hihoCoder] 第五十周: 欧拉路&#183;二

题目1 : 欧拉路·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上一回中小Hi和小Ho控制着主角收集了分散在各个木桥上的道具,这些道具其实是一块一块骨牌. 主角继续往前走,面前出现了一座石桥,石桥的尽头有一道火焰墙,似乎无法通过. 小Hi注意到在桥头有一张小纸片,于是控制主角捡起了这张纸片,只见上面写着: 将M块骨牌首尾相连放置于石桥的凹糟中,即可关闭火焰墙.切记骨牌需要数字相同才能连接. ——By 无名的冒险者 小Hi和小Ho打开了主角的道具栏,发现主角

hihoCoder 第 50 周欧拉路二之C实现方法

题目1 : 欧拉路·二 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上一回中小Hi和小Ho控制着主角收集了分散在各个木桥上的道具,这些道具其实是一块一块骨牌. 主角继续往前走,面前出现了一座石桥,石桥的尽头有一道火焰墙,似乎无法通过. 小Hi注意到在桥头有一张小纸片,于是控制主角捡起了这张纸片,只见上面写着: 将M块骨牌首尾相连放置于石桥的凹糟中,即可关闭火焰墙.切记骨牌需要数字相同才能连接. --By 无名的冒险者 小Hi和小Ho打开了主角的道具栏,发现主角

hiho欧拉路&#183;二 ----- Fleury算法求欧拉路径

hiho欧拉路·二 分析: 小Ho:这种简单的谜题就交给我吧! 小Hi:真的没问题么? <10分钟过去> 小Ho:啊啊啊啊啊!搞不定啊!!!骨牌数量一多就乱了. 小Hi:哎,我就知道你会遇到问题. 小Ho:小Hi快来帮帮我! 小Hi:好了,好了.让我们一起来解决这个问题. <小Hi思考了一下> 小Hi:原来是这样...小Ho你仔细观察这个例子: 因为相连的两个数字总是相同的,不妨我们只写一次,那么这个例子可以写成:3-2-4-3-5-1.6个数字刚好有5个间隙,每个间隙两边的数字由

hihoCoder #1176 : 欧拉路&#183;一 (简单)

题意:给出n个岛,每个岛都有桥到达其他岛,且桥数可多可少(即使两岛有多桥),判断是否是欧拉路(即每条桥只能走一次,所有桥都能遍历1遍). 思路: 满足如下条件之一者即为欧拉路: 1.连通图,每个岛的度数为偶数. 2.连通图,其中两个岛的度比为奇数. 1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N=10005; 4 vector< vector<int> > vect; 5 bool vis[

hiho一下 第五十周 题目1 : 欧拉路&#183;二

时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上一回中小Hi和小Ho控制着主角收集了分散在各个木桥上的道具,这些道具其实是一块一块骨牌. 主角继续往前走,面前出现了一座石桥,石桥的尽头有一道火焰墙,似乎无法通过. 小Hi注意到在桥头有一张小纸片,于是控制主角捡起了这张纸片,只见上面写着: 将M块骨牌首尾相连放置于石桥的凹糟中,即可关闭火焰墙.切记骨牌需要数字相同才能连接. ——By 无名的冒险者 小Hi和小Ho打开了主角的道具栏,发现主角恰好拥有M快骨牌. 小H

hiho一下 第五十周 欧拉路&#183;二

题目链接:click here~~ [题目大意] 时间限制:10000ms 单点时限:1000ms 内存限制:256MB 描述 在上一回中小Hi和小Ho控制着主角收集了分散在各个木桥上的道具,这些道具其实是一块一块骨牌. 主角继续往前走,面前出现了一座石桥,石桥的尽头有一道火焰墙,似乎无法通过. 小Hi注意到在桥头有一张小纸片,于是控制主角捡起了这张纸片,只见上面写着: 将M块骨牌首尾相连放置于石桥的凹糟中,即可关闭火焰墙.切记骨牌需要数字相同才能连接. --By 无名的冒险者 小Hi和小Ho打

hihoCoder #1182 欧拉路&#183;三 (变形)

题意:写出一个环,环上有2^n个格子,每个格子中的数字是0或1,相连着的n个格子可以组成一个数的二进制,要求给出这2^n个数字的序列,使得组成的2^n个数字全是不同的.(即从0到2^n-1) 思路:构造一个图,但是只需要考虑边,每条边假设为n个0/1组成的串,即此图有2^n条边,每边代表1个数字.若两边经过同一个点,则可以从一条边k经过 (k<<1)+0/1就是左边去掉1位,再左移一位,再在后面添加0或1,就相当于切换到另外一边.既然可以在后面添加0或1,那么就相当于一个点有两条出边,那么也就