第十场 hdu 6178 (bfs)

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!\n");system("pause");for (;;);exit(0);}
 24     }
 25     return *p1++;
 26 }
 27 inline bool blank(char ch)
 28 {
 29     return ch==‘ ‘||ch==‘\n‘||ch==‘\r‘||ch==‘\t‘;
 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\n",(k+1)/2);
 97         }
 98         else
 99         {
100             printf("%d\n",k-ans);
101         }
102     }
103     return 0;
104 }

时间: 2024-08-01 10:40:42

第十场 hdu 6178 (bfs)的相关文章

第十场 hdu 6171 Admiral(双向bfs找交点)

http://acm.hdu.edu.cn/showproblem.php?pid=6171 题目大意:给你一个塔形的数据共有1个0.2个1.3个2.4个3.5个4.6个5.你能够把0这个数据和它的上.左上.下.右下的数据进行交换.问在最多20步内能否变成按顺序排列的塔形数据?如果能输出最小步数,否则输出-1. 解题思路:因为有20步4个方向所以暴力搜索肯定是不可以的.因为有起点有终点所以我们能分两部分去搜索.但是这样搜索的话还是要去找枚举相遇的,这样的话还是会超时的,所以我们在搜索的同时还要找

2017多校第10场 HDU 6178 Monkeys 贪心,或者DP

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6178 题意:给出一棵有n个节点的树,现在需要你把k只猴子放在节点上,每个节点最多放一只猴子,且要求每只猴子必有一只另外的猴子通过一条边与它相连,问最少用多少条边能达到这个要求. 解法:利用贪心的思维,显然我们应该先选择性价比最高的,即一条边连接两个点的情况.计算出这样的边的条数ans,如果ans*2>=k,结果就是(k+1)/2,否则剩下来没有安排的猴子每一只需要多一条边,即结果为ans+k-2 *

第十场 hdu 6172 Array Challenge(矩阵快速幂)

http://acm.hdu.edu.cn/showproblem.php?pid=6172 题目大意:按照给出的公式算出an 解题思路:an=4an-1+17an-2-12an-3,不要问我为什么,我也不知道(?_?) AC代码: 1 #include <iostream> 2 #include<bits/stdc++.h> 3 //if(~i)//当i不是-1时满足条件 4 using namespace std; 5 const int SMod=1e9+7; 6 struc

2018多校第十场 HDU 6430 线段树合并

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6430 题意:一棵树上每个节点权值为v[i],每个节点的heard值是:以它为LCA的两个节点的GCD的最大值,要求输出每个节点的heard值. 题解:权值范围是[1, 1e5],1e5内数因子最多不超过200个,对每个点建一颗线段树,维护每个点的因子,dfs过程中由下往上合并线段树并更新答案. 1 #include <bits/stdc++.h> 2 using namespace std; 3

2014多校第十场1004 || HDU 4974 A simple water problem

题目链接 题意 : n支队伍,每场两个队伍表演,有可能两个队伍都得一分,也可能其中一个队伍一分,也可能都是0分,每个队伍将参加的场次得到的分数加起来,给你每个队伍最终得分,让你计算至少表演了几场. 思路 : ans = max(maxx,(sum+1)/2) :其实想想就可以,如果所有得分中最大值没有和的一半大,那就是队伍中一半一半对打,否则的话最大的那个就都包了. 1 #include <cstdio> 2 #include <cstring> 3 #include <st

【杂题总汇】HDU多校赛第十场 Videos

[HDU2018多校赛第十场]Videos 最后一场比赛也结束了-- +HDU传送门+ ◇ 题目 <简要翻译> 有n个人以及m部电影,每个人都有一个快乐值.每场电影都有它的开始.结束时间和看了这部电影会得到的快乐值.电影分成两种类型,若同一个人连续(不是时间连续,是顺序连续)看了两部相同类型的电影,他的快乐值会扣除W,数据保证扣除的值不超过电影增加的快乐值. 特别的,一个人换电影不花费时间,即若第一部电影的结束时间等于下一部电影的开始时间,是可以两场都看的:看电影必须看完:一部电影只能一个人看

hdu5336 多校联合第四场1010 模拟+bfs优先队列

http://acm.hdu.edu.cn/showproblem.php?pid=5336 Problem Description XYZ is playing an interesting game called "drops". It is played on a r?c grid. Each grid cell is either empty, or occupied by a waterdrop. Each waterdrop has a property "siz

hdu 1175 bfs 转弯题

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1175 和之前的1728类似.就是判断转弯数,建立一个用于记录转弯数的数组.. 还有就是对于特殊情况要进行考虑,比如起点与终点相同的情况,对于本题来说是不可以消去的应该输出NO.还有就是起点或终点是零这也是不行的,因为0代表没有棋子... 还有在判断能不能走的时候要小心,对于判断条件一定要小心,不要图赶快写.. 错误的地方都写在注释中了.. 代码: // hdu 1175 bfs 转弯数 //1.起点

多校第六场 HDU 4927 JAVA大数类

题目大意:给定一个长度为n的序列a,每次生成一个新的序列,长度为n-1,新序列b中bi=ai+1?ai,直到序列长度为1.输出最后的数. 思路:这题实在是太晕了,比赛的时候搞了四个小时,从T到WA,唉--对算组合还是不太了解啊,现在对组合算比较什么了-- import java.io.*; import java.math.*; import java.util.*; public class Main { public static void main(String[] args) { Sca