DFS求树的最大二分匹配+输入外挂HDU 6178 Monkeys

Posted shulin~

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了DFS求树的最大二分匹配+输入外挂HDU 6178 Monkeys相关的知识,希望对你有一定的参考价值。

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

【题意】

  • 给定一棵有n个结点的树,现在有k个猴子分布在k个结点上,我们可以删去树上的一些边,使得k个猴子每个猴子都至少和其他一个猴子相连
  • 问树上最少保留多少条边

【思路】

  • 每个猴子要至少和一个猴子相连,考虑保留的边最少,那么最优的情况一定是一条边的两个顶点放两个猴子,这些边的顶点都不重合
  • 我们现在要找到给定的树中最多有多少条这样的边,即最大二分匹配
  • O(n)的DFS,对于每个结点,优先与叶子结点形成一条边

【AC】

技术分享
  1 #include<bits/stdc++.h>
  2 using namespace std; 
  3 typedef long long ll;
  4 namespace IO
  5 {
  6     const int MX=1e8;
  7     char buf[MX];
  8     int c,sz;
  9     void begin()
 10     {
 11         c=0;
 12         sz=fread(buf,1,MX,stdin);
 13     }
 14     inline bool read(int &x)
 15     {
 16         while(c<sz && buf[c]!=- && (buf[c]<0||buf[c]>9)) ++c;
 17         if(c>=sz) return false;
 18         bool flag=0;
 19         if(buf[c]==-) flag=1,++c;
 20         for(x=0;c<sz&&buf[c]>=0&&buf[c]<=9;++c)
 21             x=x*10+buf[c]-0;
 22         if(flag) x=-x;
 23         return true;
 24     }
 25 }
 26 
 27 int n,k;
 28 const int maxn=1e5+2;
 29 const int maxm=maxn*2;
 30 bool vis[maxn];
 31 struct edge
 32 {
 33     int to;
 34     int nxt;
 35 }e[maxm];
 36 int head[maxn];
 37 int tot;
 38 //int dp[maxn][2];
 39 int flag;
 40 int cnt;
 41 void init()
 42 {
 43     memset(head,-1,sizeof(head));
 44     tot=0;
 45   //  memset(dp,0,sizeof(dp));
 46       memset(vis,false,sizeof(vis));
 47       cnt=0;
 48 }
 49 void addedge(int u,int v)
 50 {
 51     e[tot].to=v;
 52     e[tot].nxt=head[u];
 53     head[u]=tot++;
 54 }
 55 
 56 void dfs(int u,int pa)
 57 {
 58     for(int i=head[u];i!=-1;i=e[i].nxt)
 59     {
 60         int v=e[i].to;
 61         if(v==pa) continue;
 62         dfs(v,u);
 63         if(!vis[u]&&!vis[v])
 64         {
 65             cnt++;
 66             vis[u]=vis[v]=true;
 67         }
 68     }
 69 }
 70 int main()
 71 {
 72     IO::begin();
 73     int T;
 74       IO::read(T);
 75    // scanf("%d",&T);
 76     while(T--)
 77     {
 78         init();
 79       //  scanf("%d%d",&n,&k);
 80         IO::read(n);IO::read(k);
 81         int x;
 82         for(int i=2;i<=n;i++)
 83         {
 84             //scanf("%d",&x);
 85             IO::read(x);
 86             addedge(i,x);
 87             addedge(x,i);
 88         }
 89         dfs(1,-1);
 90         int tmp=cnt*2;
 91         int ans;
 92         if(k<=tmp)
 93         {
 94             ans=k/2;
 95             if(k%2) ans++;
 96         }
 97         else
 98         {
 99             ans=cnt+k-tmp;
100         }
101         printf("%d\n",ans);
102     }
103     return 0;
104 }
贪心,优先选叶子结点
技术分享
  1 #include<bits/stdc++.h>
  2 namespace fastIO {
  3 #define BUF_SIZE 1100000
  4 #define OUT_SIZE 1100000
  5 #define ll long long
  6 // fread->read
  7 bool IOerror = 0;
  8 inline char nc() {
  9     static char buf[BUF_SIZE], *p1 = buf + BUF_SIZE, *pend = buf + BUF_SIZE;
 10     if (p1 == pend) {
 11         p1 = buf;
 12         pend = buf + fread(buf, 1, BUF_SIZE, stdin);
 13         if (pend == p1) {
 14             IOerror = 1;
 15             return -1;
 16         }
 17         //{printf("IO error!\n");system("pause");for (;;);exit(0);}
 18     }
 19     return *p1++;
 20 }
 21 inline bool blank(char ch) {
 22     return ch ==   || ch == \n || ch == \r || ch == \t;
 23 }
 24 inline void read(int &x) {
 25     bool sign = 0;
 26     char ch = nc();
 27     x = 0;
 28     for (; blank(ch); ch = nc())
 29         ;
 30     if (IOerror) return;
 31     if (ch == -) sign = 1, ch = nc();
 32     for (; ch >= 0 && ch <= 9; ch = nc()) x = x * 10 + ch - 0;
 33     if (sign) x = -x;
 34 }
 35 inline void read(ll &x) {
 36     bool sign = 0;
 37     char ch = nc();
 38     x = 0;
 39     for (; blank(ch); ch = nc())
 40         ;
 41     if (IOerror) return;
 42     if (ch == -) sign = 1, ch = nc();
 43     for (; ch >= 0 && ch <= 9; ch = nc()) x = x * 10 + ch - 0;
 44     if (sign) x = -x;
 45 }
 46 inline void read(double &x) {
 47     bool sign = 0;
 48     char ch = nc();
 49     x = 0;
 50     for (; blank(ch); ch = nc())
 51         ;
 52     if (IOerror) return;
 53     if (ch == -) sign = 1, ch = nc();
 54     for (; ch >= 0 && ch <= 9; ch = nc()) x = x * 10 + ch - 0;
 55     if (ch == .) {
 56         double tmp = 1;
 57         ch = nc();
 58         for (; ch >= 0 && ch <= 9; ch = nc()) tmp /= 10.0, x += tmp * (ch - 0);
 59     }
 60     if (sign) x = -x;
 61 }
 62 inline void read(char *s) {
 63     char ch = nc();
 64     for (; blank(ch); ch = nc())
 65         ;
 66     if (IOerror) return;
 67     for (; !blank(ch) && !IOerror; ch = nc()) *s++ = ch;
 68     *s = 0;
 69 }
 70 inline void read(char &c) {
 71     for (c = nc(); blank(c); c = nc())
 72         ;
 73     if (IOerror) {
 74         c = -1;
 75         return;
 76     }
 77 }
 78 // getchar->read
 79 inline void read1(int &x) {
 80     char ch;
 81     int bo = 0;
 82     x = 0;
 83     for (ch = getchar(); ch < 0 || ch > 9; ch = getchar())
 84         if (ch == -) bo = 1;
 85     for (; ch >= 0 && ch <= 9; x = x * 10 + ch - 0, ch = getchar())
 86         ;
 87     if (bo) x = -x;
 88 }
 89 inline void read1(ll &x) {
 90     char ch;
 91     int bo = 0;
 92     x = 0;
 93     for (ch = getchar(); ch < 0 || ch > 9; ch = getchar())
 94         if (ch == -) bo = 1;
 95     for (; ch >= 0 && ch <= 9; x = x * 10 + ch - 0, ch = getchar())
 96         ;
 97     if (bo) x = -x;
 98 }
 99 inline void read1(double &x) {
100     char ch;
101     int bo = 0;
102     x = 0;
103     for (ch = getchar(); ch < 0 || ch > 9; ch = getchar())
104         if (ch == -) bo = 1;
105     for (; ch >= 0 && ch <= 9; x = x * 10 + ch - 0, ch = getchar())
106         ;
107     if (ch == .) {
108         double tmp = 1;
109         for (ch = getchar(); ch >= 0 && ch <= 9; tmp /= 10.0, x += tmp * (ch - 0), ch = getchar())
110             ;
111     }
112     if (bo) x = -x;
113 }
114 inline void read1(char *s) {
115     char ch = getchar();
116     for (; blank(ch); ch = getchar())
117         ;
118     for (; !blank(ch); ch = getchar()) *s++ = ch;
119     *s = 0;
120 }
121 inline void read1(char &c) {
122     for (c = getchar(); blank(c); c = getchar())
123         ;
124 }
125 // scanf->read
126 inline void read2(int &x) {
127     scanf("%d", &x);
128 }
129 inline void read2(ll &x) {
130 #ifdef _WIN32
131     scanf("%I64d", &x);
132 #else
133 #ifdef __linux
134     scanf("%lld", &x);
135 #else
136     puts("error:can‘t recognize the system!");
137 #endif
138 #endif
139 }
140 inline void read2(double &x) {
141     scanf("%lf", &x);
142 }
143 inline void read2(char *s) {
144     scanf("%s", s);
145 }
146 inline void read2(char &c) {
147     scanf(" %c", &c);
148 }
149 inline void readln2(char *s) {
150     gets(s);
151 }
152 // fwrite->write
153 struct Ostream_fwrite {
154     char *buf, *p1, *pend;
155     Ostream_fwrite() {
156         buf = new char[BUF_SIZE];
157         p1 = buf;
158         pend = buf + BUF_SIZE;
159     }
160     void out(char ch) {
161         if (p1 == pend) {
162             fwrite(buf, 1, BUF_SIZE, stdout);
163             p1 = buf;
164         }
165         *p1++ = ch;
166     }
167     void print(int x) {
168         static char s[15], *s1;
169         s1 = s;
170         if (!x) *s1++ = 0;
171         if (x < 0) out(-), x = -x;
172         while (x) *s1++ = x % 10 + 0, x /= 10;
173         while (s1-- != s) out(*s1);
174     }
175     void println(int x) {
176         static char s[15], *s1;
177         s1 = s;
178         if (!x) *s1++ = 0;
179         if (x < 0) out(-), x = -x;
180         while (x) *s1++ = x % 10 + 0, x /= 10;
181         while (s1-- != s) out(*s1);
182         out(\n);
183     }
184     void print(ll x) {
185         static char s[25], *s1;
186         s1 = s;
187         if (!x) *s1++ = 0;
188         if (x < 0) out(-), x = -x;
189         while (x) *s1++ = x % 10 + 0, x /= 10;
190         while (s1-- != s) out(*s1);
191     }
192     void println(ll x) {
193         static char s[25], *s1;
194         s1 = s;
195         if (!x) *s1++ = 0;
196         if (x < 0) out(-), x = -x;
197         while (x) *s1++ = x % 10 + 0, x /= 10;
198         while (s1-- != s) out(*s1);
199         out(\n);
200     }
201     void print(double x, int y) {
202         static ll mul[] = {1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000, 10000000000LL, 100000000000LL, 1000000000000LL, 10000000000000LL, 100000000000000LL, 1000000000000000LL, 10000000000000000LL, 100000000000000000LL};
203         if (x < -1e-12) out(-), x = -x;
204         x *= mul[y];
205         ll x1 = (ll) floor(x);
206         if (x - floor(x) >= 0.5) ++x1;
207         ll x2 = x1 / mul[y], x3 = x1 - x2 * mul[y];
208         print(x2);
209         if (y > 0) {
210             out(.);
211             for (size_t i = 1; i < y && x3 * mul[i] < mul[y]; out(0), ++i)
212                 ;
213             print(x3);
214         }
215     }
216     void println(double x, int y) {
217         print(x, y);
218         out(\n);
219     }
220     void print(char *s) {
221         while (*s) out(*s++);
222     }
223     void println(char *s) {
224         while (*s) out(*s++);
225         out(\n);
226     }
227     void flush() {
228         if (p1 != buf) {
229             fwrite(buf, 1, p1 - buf, stdout);
230             p1 = buf;
231         }
232     }
233     ~Ostream_fwrite() {
234         flush();
235     }
236 } Ostream;
237 inline void print(int x) {
238     Ostream.print(x);
239 }
240 inline void println(int x) {
241     Ostream.println(x);
242 }
243 inline void print(char x) {
244     Ostream.out(x);
245 }
246 inline void println(char x) {
247     Ostream.out(x);
248     Ostream.out(\n);
249 }
250 inline void print(ll x) {
251     Ostream.print(x);
252 }
253 inline void println(ll x) {
254     Ostream.println(x);
255 }
256 inline void print(double x, int y) {
257     Ostream.print(x, y);
258 }
259 inline void println(double x, int y) {
260     Ostream.println(x, y);
261 }
262 inline void print(char *s) {
263     Ostream.print(s);
264 }
265 inline void println(char *s) {
266     Ostream.println(s);
267 }
268 inline void println() {
269     Ostream.out(\n);
270 }
271 inline void flush() {
272     Ostream.flush();
273 }
274 // puts->write
275 char Out[OUT_SIZE], *o = Out;
276 inline void print1(int x) {
277     static char buf[15];
278     char *p1 = buf;
279     if (!x) *p1++ = 0;
280     if (x < 0) *o++ = -, x = -x;
281     while (x) *p1++ = x % 10 + 0, x /= 10;
282     while (p1-- != buf) *o++ = *p1;
283 }
284 inline void println1(int x) {
285     print1(x);
286     *o++ = \n;
287 }
288 inline void print1(ll x) {
289     static char buf[25];
290     char *p1 = buf;
291     if (!x) *p1++ = 0;
292     if (x < 0) *o++ = -, x = -x;
293     while (x) *p1++ = x % 10 + 0, x /= 10;
294     while (p1-- != buf) *o++ = *p1;
295 }
296 inline void println1(ll x) {
297     print1(x);
298     *o++ = \n;
299 }
300 inline void print1(char c) {
301     *o++ = c;
302 }
303 inline void println1(char c) {
304     *o++ = c;
305     *o++ = \n;
306 }
307 inline void print1(char *s) {
308     while (*s) *o++ = *s++;
309 }
310 inline void println1(char *s) {
311     print1(s);
312     *o++ = \n;
313 }
314 inline void println1() {
315     *o++ = \n;
316 }
317 inline void flush1() {
318     if (o != Out) {
319         if (*(o - 1) == \n) *--o = 0;
320         puts(Out);
321     }
322 }
323 struct puts_write {
324     ~puts_write() {
325         flush1();
326     }
327 } _puts;
328 inline void print2(int x) {
329     printf("%d", x);
330 }
331 inline void println2(int x) {
332     printf("%d\n", x);
333 }
334 inline void print2(char x) {
335     printf("%c", x);
336 }
337 inline void println2(char x) {
338     printf("%c\n", x);
339 }
340 inline void print2(ll x) {
341 #ifdef _WIN32
342     printf("%I64d", x);
343 #else
344 #ifdef __linux
345     printf("%lld", x);
346 #else
347     puts("error:can‘t recognize the system!");
348 #endif
349 #endif
350 }
351 inline void println2(ll x) {
352     print2(x);
353     printf("\n");
354 }
355 inline void println2() {
356     printf("\n");
357 }
358 #undef ll
359 #undef OUT_SIZE
360 #undef BUF_SIZE
361 };
362 using namespace fastIO;
363 typedef long long ll;
364 int n,k;
365 const int maxn=1e5+2;
366 const int maxm=maxn*2;
367 struct edge
368 {
369     int to;
370     int nxt;
371 }e[maxm];
372 int head[maxn];
373 int tot;
374 int dp[maxn][2];
375 
376 void init()
377 {
378     memset(head,-1,sizeof(head));
379     tot=0;
380     memset(dp,0,sizeof(dp));
381 }
382 void addedge(int u,int v)
383 {
384     e[tot].to=v;
385     e[tot].nxt=head[u];
386     head[u]=tot++;
387 }
388 
389 bool dfs(int u,int pa)
390 {
391     int flag=0;
392     dp[u][0]=0;
393     for(int i=head[u];i!=-1;i=e[i].nxt)
394     {
395         int v=e[i].to;
396         if(v==pa) continue;
397         if(dfs(v,u))
398         {
399             flag=1;
400         }
401         dp[u][0]+=dp[v][1];
402     }
403     if(flag)
404     {
405         dp[u][1]=dp[u][0]+1;
406         return false;
407     }
408     else
409     {
410         dp[u][1]=dp[u][0];
411         return true;
412     }
413 }
414 int main()
415 {
416     int T;
417     //scanf("%d",&T);
418     read(T);
419     //cout<<T<<endl;
420     while(T--)
421     {
422         init();
423         read(n);
424         read(k);
425         //cout<<n<<k<<endl;
426         //scanf("%d%d",&n,&k);
427         int x;
428         for(int i=2;i<=n;i++)
429         {
430             read(x);
431             //scanf("%d",&x);
432             addedge(i,x);
433             addedge(x,i);
434         }
435         dfs(1,-1);
436         int cnt=dp[1][1];
437         int tmp=cnt*2;
438         int ans;
439         if(k<=tmp)
440         {
441             ans=k/2;
442             if(k%2) ans++;
443         }
444         else
445         {
446             ans=cnt+k-tmp;
447         }
448         printf("%d\n",ans);
449     }
450     return 0;
451 }
树形dp

树形dp的代码比赛是wa了,赛后才发现,原来是我dfs里开了全局变量flag,flag在其他层里被修改,改成局部变量就A了orz

以上是关于DFS求树的最大二分匹配+输入外挂HDU 6178 Monkeys的主要内容,如果未能解决你的问题,请参考以下文章

求树的直径+并查集(bfs,dfs都可以)hdu4514

HDU 4612 Warm up(双连通分量缩点+求树的直径)

求树的重心

hdu2196 树形dp经典|树的直径

HDU6178 Monkeys

01染色法判断二分匹配+匈牙利算法求最大匹配HDU The Accomodation of Students