题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6178
题意:希望在一棵树中删掉最多的边,使得剩下的k个点至少有一个点相连。
比赛时候学弟贪心dfs过的,然后发现这个题实际上是最大匹配。
任意两点相连代表匹配中的一条边,最大匹配后的结果就是树上最多有多少点对两两有边。
考虑最大匹配Max>=k的时候,直接两两配对即可,答案就是k/2取上整。
Max<k的时候就是k-Max/2取下整。
朝鲜也流行卡常啊?我夸夸你们啊?
1 #include <bits/stdc++.h> 2 using namespace std; 3 4 typedef struct Edge { int v, next; }Edge; 5 const int maxn = 100005; 6 const int inf = 0x3f3f3f3f; 7 int nx, ny, dist; 8 int Mx[maxn], My[maxn], dx[maxn], dy[maxn], vis[maxn]; 9 int head[maxn], ecnt; 10 Edge edge[maxn<<1]; 11 12 int n, m; 13 void init() { 14 memset(head, -1, sizeof(head)); 15 for(int i = 0; i < maxn; i++) edge[i].next = -1; 16 ecnt = 0; 17 } 18 19 void adde(int u, int v) { 20 edge[ecnt].v = v; 21 edge[ecnt].next = head[u]; head[u] = ecnt++; 22 } 23 24 bool Dfs(int u) { 25 for(int i = head[u]; ~i; i=edge[i].next) { 26 int& v = edge[i].v; 27 if(!vis[v] && dy[v] == dx[u] + 1) { 28 vis[v] = 1; 29 if(My[v] != -1 && dy[v] == dist) continue; 30 if(My[v] == -1 || Dfs(My[v])) { 31 My[v] = u; 32 Mx[u] = v; 33 return 1; 34 } 35 } 36 } 37 return 0; 38 } 39 bool Search() { 40 queue<int> Q; 41 dist = inf; 42 memset(dx, -1, sizeof(dx)); 43 memset(dy, -1, sizeof(dy)); 44 for(int i = 0; i < nx; i++) { 45 if(Mx[i] == -1) { 46 Q.push(i), dx[i] = 0; 47 } 48 } 49 while(!Q.empty()) { 50 int u = Q.front(); 51 if(dx[u] > dist) break; 52 Q.pop(); 53 for(int i = head[u]; ~i; i=edge[i].next) { 54 int& v = edge[i].v; 55 if(dy[v] == -1) { 56 dy[v] = dx[u] + 1; 57 if(My[v] == -1) dist = dy[v]; 58 else { 59 dx[My[v]] = dy[v] + 1; 60 Q.push(My[v]); 61 } 62 } 63 } 64 } 65 return dist != inf; 66 } 67 68 int MaxMatch() { 69 int res = 0; 70 memset(Mx, -1, sizeof(Mx)); 71 memset(My, -1, sizeof(My)); 72 while(Search()) { 73 memset(vis, 0, sizeof(vis)); 74 for(int i = 0; i < nx; i++) { 75 if(Mx[i] == -1 && Dfs(i)) res++; 76 } 77 } 78 if(res >= m) return (m + 1) / 2; 79 else return m - res / 2; 80 } 81 82 namespace fastIO { 83 #define BUF_SIZE 100000 84 //fread -> read 85 bool IOerror = 0; 86 inline char nc() { 87 static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE; 88 if (p1 == pend) { 89 p1 = buf; 90 pend = buf + fread(buf, 1, BUF_SIZE, stdin); 91 if (pend == p1) { 92 IOerror = 1; 93 return -1; 94 } 95 } 96 return *p1++; 97 } 98 inline bool blank(char ch) { 99 return ch == ' ' || ch == ' ' || ch == ' ' || ch == ' '; 100 } 101 inline void read(int &x) { 102 char ch; 103 while (blank(ch = nc())); 104 if (IOerror) 105 return; 106 for (x = ch - '0'; (ch = nc()) >= '0' && ch <= '9'; x = x * 10 + ch - '0'); 107 } 108 #undef BUF_SIZE 109 }; 110 111 112 signed main() { 113 // freopen("in", "r", stdin); 114 int T, u; 115 fastIO::read(T); 116 while(T--) { 117 init(); 118 fastIO::read(n); fastIO::read(m); 119 nx = ny = n; 120 for(int i = 2; i <= n; i++) { 121 fastIO::read(u); 122 adde(u-1, i-1), adde(i-1, u-1); 123 } 124 printf("%d ", MaxMatch()); 125 } 126 return 0; 127 }