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 ",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! ");system("pause");for (;;);exit(0);} 18 } 19 return *p1++; 20 } 21 inline bool blank(char ch) { 22 return ch == ' ' || ch == ' ' || ch == ' ' || ch == ' '; 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(' '); 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(' '); 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(' '); 219 } 220 void print(char *s) { 221 while (*s) out(*s++); 222 } 223 void println(char *s) { 224 while (*s) out(*s++); 225 out(' '); 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(' '); 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(' '); 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++ = ' '; 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++ = ' '; 299 } 300 inline void print1(char c) { 301 *o++ = c; 302 } 303 inline void println1(char c) { 304 *o++ = c; 305 *o++ = ' '; 306 } 307 inline void print1(char *s) { 308 while (*s) *o++ = *s++; 309 } 310 inline void println1(char *s) { 311 print1(s); 312 *o++ = ' '; 313 } 314 inline void println1() { 315 *o++ = ' '; 316 } 317 inline void flush1() { 318 if (o != Out) { 319 if (*(o - 1) == ' ') *--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 ", x); 333 } 334 inline void print2(char x) { 335 printf("%c", x); 336 } 337 inline void println2(char x) { 338 printf("%c ", 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(" "); 354 } 355 inline void println2() { 356 printf(" "); 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 ",ans); 449 } 450 return 0; 451 }
树形dp的代码比赛是wa了,赛后才发现,原来是我dfs里开了全局变量flag,flag在其他层里被修改,改成局部变量就A了orz