[HDOJ6178]Monkeys(二分图最大匹配)

题目链接: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 == '\n' || ch == '\r' || ch == '\t';
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\n", MaxMatch());
125     }
126     return 0;
127 }

 

posted @ 2017-08-24 19:25  Kirai  阅读(169)  评论(0编辑  收藏  举报