http://acm.hdu.edu.cn/showproblem.php?pid=6178
题目大意:
已知n个节点有n-1条连线,现在有k只猴子,每只猴子必须要住在一个节点上,两只猴子之间最少要有一条连线。问k只猴子最少要有多少条连线。
解题思路:
首先由于数据太大而且要在1s内完成所以应该用输入挂输入。测试了一下如果用scanf输入耗时995ms,如果用输入挂的话耗时421ms。
然后能够知道在一棵树中如果有成对的节点,可以知道节省的节点数最多就是成对的节点的个数。所以求出树的成对的节点个数是解决问题的关键。
最后找出度为1的节点放入队列中。使用bfs访问队列值now,然后找出它的子节点next,如果now和next都没有被访问过就把他们标记成访问,顺便把对数+1。然后在next的容器中删除now这个值,如果next容器的size是1,就把它放入队列中.
AC代码:
1 #include <iostream> 2 #include<bits/stdc++.h> 3 using namespace std; 4 namespace fastIO 5 { 6 #define BUF_SIZE 100000 7 #define OUT_SIZE 100000 8 #define ll long long 9 //fread->read 10 bool IOerror=0; 11 inline char nc() 12 { 13 static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE; 14 if (p1==pend) 15 { 16 p1=buf; 17 pend=buf+fread(buf,1,BUF_SIZE,stdin); 18 if (pend==p1) 19 { 20 IOerror=1; 21 return -1; 22 } 23 //{printf("IO error! ");system("pause");for (;;);exit(0);} 24 } 25 return *p1++; 26 } 27 inline bool blank(char ch) 28 { 29 return ch==' '||ch==' '||ch==' '||ch==' '; 30 } 31 inline void read(int &x) 32 { 33 bool sign=0; 34 char ch=nc(); 35 x=0; 36 for (; blank(ch); ch=nc()); 37 if (IOerror)return; 38 if (ch=='-')sign=1,ch=nc(); 39 for (; ch>='0'&&ch<='9'; ch=nc())x=x*10+ch-'0'; 40 if (sign)x=-x; 41 } 42 } 43 using namespace fastIO; 44 int degr[100005],vis[100005]; 45 vector<int>vec[100005]; 46 queue<int>que; 47 int main() 48 { 49 int n,t,k,x; 50 //freopen("1008.in","r",stdin); 51 read(t); 52 while(t--) 53 { 54 read(n); 55 read(k); 56 for(int i=0; i<=n; i++) 57 { 58 vec[i].clear(); 59 degr[i]=0; 60 vis[i]=0; 61 } 62 for(int i=2; i<=n; i++) 63 { 64 read(x); 65 vec[i].push_back(x); 66 vec[x].push_back(i); 67 degr[i]++; 68 degr[x]++; 69 } 70 for(int i=1; i<=n; i++) 71 { 72 if(degr[i]==1) 73 { 74 que.push(i); 75 } 76 degr[i]=0; 77 } 78 int ans=0; 79 while(!que.empty()) 80 { 81 int val=que.front(); 82 que.pop(); 83 int now=vec[val][0]; 84 if(vis[now]==0&&vis[val]==0) 85 { 86 ans++; 87 vis[now]=1; 88 vis[val]=1; 89 } 90 vec[now].erase(remove(vec[now].begin(),vec[now].end(),val),vec[now].end()); 91 if(vec[now].size()==1) 92 que.push(now); 93 } 94 if(ans*2>k) 95 { 96 printf("%d ",(k+1)/2); 97 } 98 else 99 { 100 printf("%d ",k-ans); 101 } 102 } 103 return 0; 104 }