【Codeforces858F】Wizard's Tour [构造]

Wizard's Tour

Time Limit: 50 Sec  Memory Limit: 512 MB

Description

  

Input

  

Output

  

Sample Input

  4 5
  1 2
  3 2
  2 4
  3 4
  4 1

Sample Output

  2
  4 1 2
  4 3 2

HINT

  

Solution

  首先,一个连通块的答案可以是floor(m / 2)。考虑如何构造出一种解。

  首先我们先搞出一个dfs树

  那么现在对于一个点,有三种边:1. 非树边;2. 儿子边;3. 父亲边

  我们将非树边儿子边优先级看做一样的父亲边优先级最低

  考虑将配给,即这个点是一种走法中的中点。从叶子节点往上做。两两配对这些边

  显然每条边都被尽可能利用了,最后只有与根相连的边可能会有最多一条用不了。

  这样就是一种解了。

Code

 1 #include<iostream>
 2 #include<string>
 3 #include<algorithm>
 4 #include<cstdio>
 5 #include<cstring>
 6 #include<cstdlib>
 7 #include<cmath>
 8 #include<vector>
 9 using namespace std;
10 typedef long long s64;
11 
12 const int ONE = 400005;
13 const int MOD = 1e9 + 7;
14 
15 int get()
16 {
17         int res = 1, Q = 1; char c;
18         while( (c = getchar()) < 48 || c > 57)
19             if(c == '-') Q = -1;
20         if(Q) res = c - 48;
21         while( (c = getchar()) >= 48 && c <= 57)
22             res = res * 10 + c - 48;
23         return res * Q;
24 }
25 
26 int ans_len;
27 struct power
28 {
29         int l, mid, r;
30 }Ans[ONE * 2];
31 
32 int n, m;
33 int x, y;
34 int next[ONE * 2], first[ONE], go[ONE * 2], tot;
35 int vis[ONE * 2];
36 
37 void Add(int u, int v)
38 {
39         next[++tot] = first[u], first[u] = tot, go[tot] = v;
40         next[++tot] = first[v], first[v] = tot, go[tot] = u;
41 }
42 
43 vector <power> A;
44 int fat[ONE];
45 
46 void Dfs(int u)
47 {
48         for(int e = first[u]; e; e = next[e])
49         {
50             int v = go[e];
51             if(fat[v] || vis[e]) continue;
52             fat[v] = u, Dfs(v);
53         }
54 
55         A.clear();
56         for(int e = first[u]; e; e = next[e])
57             if(!vis[e] && fat[u] != go[e]) A.push_back((power){go[e], 0, e});
58         for(int e = first[u]; e; e = next[e])
59             if(!vis[e] && fat[u] == go[e]) A.push_back((power){go[e], 0, e});
60 
61         int p = 0, len = A.size();
62         for(int j = 0; j + 1 < len; j += 2)
63         {
64             vis[A[j].r] = vis[(A[j].r-1^1)+1] = 1;
65             vis[A[j+1].r] = vis[(A[j+1].r-1^1)+1] = 1;
66             Ans[++ans_len] = (power){A[j].l, u, A[j + 1].l};
67         }
68 }
69 
70 int main()
71 {
72         n = get();    m = get();
73         for(int i = 1; i <= m; i++)
74             x = get(), y = get(), Add(x, y);
75         
76         for(int i = 1; i <= n; i++)
77             if(!fat[i]) Dfs(i);
78 
79         printf("%d\n", ans_len);
80         for(int i = 1; i <= ans_len; i++)
81             printf("%d %d %d\n", Ans[i].l, Ans[i].mid, Ans[i].r);
82 }
View Code

 

转载于:https://www.cnblogs.com/BearChild/p/7895789.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值