传送门:欧拉路·二
#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