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 ", 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(* ̄▽ ̄*)ブ~