Problem A: Krito的讨伐
Description
Krito终于干掉了99层的boss,来到了第100层。第100层可以表示成一颗树,这棵树有n个节点(编号从0到n-1),树上每一个节点可能有很多只怪物。 Krito现在在0号节点,现在它想要区清除这一层所有的怪物。他现在有atk大小的攻击力。只有当你的攻击力大于这只怪物的防御力时,你才可以打败他,同时每打败只怪物,你会获得一定的攻击力加成。一个节点可能存在着不止一只怪兽,你要打败这个节点的所有怪物才能可以从这个节点通过,请问他能不能完成这个任务?注意:不要求一次性杀光一个节点里面的所有怪物。
相关知识: 摘自维基百科
在计算机科学中,树(英语:tree)是一种抽象资料型别(ADT)或是实作这种抽象资料型别的数据结构,用来模拟具树状结构性质的资料集合。它是由n(n>=1)个有限节点组成一个具有层次关系的集合。把它叫做“树”是因为它看起来像一棵倒挂的树,也就是说它是根朝上,而叶朝下的。它具有以下的特点:
1.每个节点有零个或多个子节点;
2.没有父节点的节点称为根节点;
3.每一个非根节点有且只有一个父节点;
4.除了根节点外,每个子节点可以分为多个不相交的子树;
Input
第1行:一个数T,表示有T个测试样例(0<=T<=50) ,接下来有T个测试样例
对于每一个测试样例:
第1行:两个整数n,m表示这棵树有n个节点,m只怪兽(0<=n<=1000 ,0<=m <=100)
第2至n-1行: 两个整数u,v表示编号为u,v之间的节点有一条无向边,题目保证不会成环。(0<=u,v<n , u!=v)
第3行: 一个整数atk,表示Krito的初始化攻击力(0<=atk<=100)
第4至3+m行:两个整数id,def,add_atk,表示在编号为id的点上,有一只防御力为def的怪物,打败后可以增加add_atk点的攻击力。(0<=add_atk,def<=100)
Output
对于每一个测试样例,如果Krito能够清除所有的怪物,则输出“Oh yes.” 否则,输出“Good Good Study,Day Day Up.”
Sample Input
Sample Output
题意:告诉一颗树,然后一些结点,每个结点中可能有一些怪,每个怪都有一定防御力,开始攻击力有初始值,当攻击力大于怪的防御力时候可以打死怪,然后获得一定攻击力增长,只有打死一个结点的所有怪之后才能通过该点继续扩展,问能够消灭所有怪。
思路:从根节点开始,每次按顺序扩展,把可以扩展到的怪都加到优先队列,然后把能打的怪都打死,一次扩展相邻结点
#include <iostream>
#include <string>
#include <cstring>
#include <stdio.h>
#include <algorithm>
#include <cmath>
#include <queue>
#include <vector>
using namespace std;
int n,m;
int u,v;
int atk;
int num[2009];
int vis[2009];
struct Node
{
int id,def,add;
Node() {};
Node(int a,int b,int c)
{
id=a;
def=b;
add=c;
}
int operator<(const Node &n)const
{
return def>n.def;
}
};
vector<int>vt[2009];
vector<Node>guai[2009];
priority_queue< Node >pq;
void dfs(int x)
{
if(num[x]!=0)
{
for(int i=0; i<guai[x].size(); i++)
{
pq.push(guai[x][i]);
}
guai[x].clear(); //加入一次后要清空,若再进入会重新加
return;
}
for(int i=0; i<vt[x].size(); i++) //当前节点没有怪,则扩展到其他节点
{
if(vis[vt[x][i]]==0)
{
vis[vt[x][i]]=1;
dfs(vt[x][i]);
}
}
}
int fun()
{
while(!pq.empty()) pq.pop(); //每次开始事要先清空
int cnt=0;
vis[cnt]=1;
dfs(cnt);
while(!pq.empty())
{
Node tmp=pq.top();
pq.pop();
if(atk<=tmp.def)
return 0;
atk+=tmp.add;
cnt=tmp.id;
num[cnt]--;
dfs(cnt);
}
return 1;
}
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d",&n,&m);
for(int i=0; i<=n; i++)
{
vt[i].clear();
guai[i].clear();
vis[i]=0;
num[i]=0;
}
// memset(vis,0,sizeof vis);
// memset(num,0,sizeof num);
for(int i=0; i<n-1; i++)
{
scanf("%d%d",&u,&v);
vt[u].push_back(v);
vt[v].push_back(u);
}
scanf("%d",&atk);
int a,b,c;
for(int i=0; i<m; i++)
{
scanf("%d%d%d",&a,&b,&c);
num[a]++; //当前该节点怪的数量
guai[a].push_back(Node(a,b,c)); //当前节点怪的集合
}
if(fun()==0)
puts("Good Good Study,Day Day Up.");
else
puts("Oh yes.");
}
return 0;
}