1003 Cover(hdu 6311)

http://acm.hdu.edu.cn/showproblem.php?pid=6311

题意:给你一个无向非连通图(王的北疆),要求每个士兵守卫(覆盖)一条路径(空守哨站QAQ),最少需要多少个士兵?每个士兵守卫的疆域(路径)是?

          即给你一个图,问你最少几次一笔画可以画完。

思路:把每个联通快中度为奇数的点两两相连(留下一对作为欧拉路径的首尾)后,可以构造出这n个点的欧拉路径(一笔画游戏QAQ),把后补的线(id=0)去掉后剩余的几个路径便是每个士兵守卫的那部分疆域。

 官方题解:

每个连通块显然是独立的。对于一个连通块(除了单个点的),如果奇度数点个数为 k,那么至少需要 max(k/2, 1)条路径。我们将奇度数点两两配对连边,求出欧拉回路,然后把这些边删掉,就可以变成恰好 max(k/2, 1)条路径。
复杂度 O(m+n)。

喜大普奔,官方题解说人话了!!!而且思路清晰有理有据,不像百度的题解都是上来就说啊呀这个要用欧拉路径不说为啥。QAQ。。。

 

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 const int N = 1e5 + 5;
 5 
 6 struct edge{
 7     int from, to, id, vis;
 8 };
 9 vector<edge> e;
10 vector<int> G[N], ans[N];///num in edge.
11 vector<int> point, ac;
12 int n, m, deg[N], vis[N], res;
13 
14 void init(){
15     res = 0;
16     for(int i = 0; i <= n; i++){
17         G[i].clear();
18         ans[i].clear();
19     }
20     //point.clear(), ac.clear(),
21     e.clear();
22     memset(deg, 0, sizeof deg);
23     memset(vis, 0, sizeof vis);
24 }
25 
26 void add(int from, int to, int id){
27     e.push_back(edge{from, to, id, 0});///{}
28     e.push_back(edge{to, from, -id, 0});
29     int pos = e.size();
30     G[from].push_back(pos - 2);
31     G[to].push_back(pos - 1);
32     deg[from]++, deg[to]++;
33 }
34 void dfs1(int u){
35     vis[u] = 1;
36     if(deg[u] & 1) point.push_back(u);
37     int l = G[u].size();
38     for(int i = 0; i < l; i++){
39         edge &ed = e[G[u][i]];
40         if(!vis[ed.to]) dfs1(ed.to);
41     }
42 }
43 void dfs2(int u){
44     int l = G[u].size();
45     for(int i = 0; i < l; i++){
46         edge &ed = e[G[u][i]];
47         if(ed.vis) continue;
48         ed.vis = e[G[u][i]^1].vis = 1;
49         dfs2(ed.to);
50         ac.push_back(ed.id);
51     }
52 }
53 
54 int main()
55 {
56     while(~scanf("%d %d", &n, &m)){
57         init();///
58         int u, v;
59         for(int i = 1; i <= m; i++){
60             scanf("%d %d", &u, &v);
61             add(u, v, i);
62         }
63         for(int i = 1; i <= n; i++){
64             if(vis[i] || deg[i] == 0) continue;
65             point.clear();
66             dfs1(i);
67             int l = point.size();
68             for(int j = 2; j < l; j += 2) add(point[j], point[j + 1], 0);
69             ac.clear();
70             int t = point.empty()? i: point[0];
71             dfs2(t);
72             for(int j = ac.size() - 1; j >= 0; j--){
73                 if(ac[j] == 0) continue;
74                 res++;
75                 while(ac[j] != 0 && j >= 0){
76                     ans[res].push_back(ac[j]);
77                     j--;///
78                 }
79                 //j++;???don't make any influence.
80             }
81         }
82         printf("%d\n", res);
83         for(int i = 1; i <= res; i++){
84             int l = ans[i].size();
85             printf("%d", l);
86             for(int j = 0; j < l; j++) printf(" %d", ans[i][j]);
87             puts("");
88         }
89     }
90     return 0;
91 }

 

突然就懈怠了,还有一题(笛卡尔树)只看了题解了解了思路就假装补完了。。。感觉补题补得心累,发现队友也看不进去了最终三只选择肥寝。

PS:竹一楼下水果店和商店暑假不关门开心!买到了汪叽哒蓝朋友口味哒可爱多开心o(* ̄▽ ̄*)ブ~

posted on 2018-07-29 16:14  雪藤  阅读(112)  评论(0编辑  收藏  举报