码迷,mamicode.com
首页 > 其他好文 > 详细

hihocoder 1181 欧拉路.二

时间:2015-07-08 20:30:40      阅读:111      评论:0      收藏:0      [点我收藏+]

标签:

传送门:欧拉路·二

#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行是如何删边的。我们看到这种用数组实现的临界表是比较灵活与实用的。

 

 

 

 

 
 
 
 
 
 

 

hihocoder 1181 欧拉路.二

标签:

原文地址:http://www.cnblogs.com/Patt/p/4630941.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!