Description
Krito终于干掉了99层的boss,来到了第100层。第100层可以表示成一颗树,这棵树有n个节点(编号从0到n-1),树上每一个节点可能有很多只怪物。 Krito现在在0号节点,现在它想要区清除这一层所有的怪物。他现在有atk大小的攻击力。只有当你的攻击力大于这只怪物的防御力时,你才可以打败他,同时每打败只怪物,你会获得一定的攻击力加成。一个节点可能存在着不止一只怪兽,你要打败这个节点的所有怪物才能可以从这个节点通过,请问他能不能完成这个任务?注意:不要求一次性杀光一个节点里面的所有怪物。
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
15 20 10 22 32 4113 10 21 11 0
Sample Output
Oh yes.
利用有限队列可以解决此问题
利用有限队列可以解决此问题
#include <iostream>
#include <vector>
#include <queue>
#include <cstring>
#include <cstdio>
using namespace std;
const int MAX_N = 1009;
int n, m, atk;
struct Node
{
int id;
int def;
int add;
// 自定义优先队列的排列规则
friend bool operator<(Node a, Node b)
{
return a.def > b.def;
}
};
int g[MAX_N][MAX_N]; // 邻接矩阵模拟树
int cnt[MAX_N]; // 每个节点上的怪物
vector<Node> v[MAX_N]; // 每个节点上的全部怪物信息
bool visit[MAX_N]; // 标记该点是否访问过
// 初始化
void init()
{
memset(g, 0, sizeof(g));
memset(cnt, 0, sizeof(cnt));
memset(visit, false, sizeof(visit));
for(int i = 0; i < MAX_N; i++)
v[i].clear();
}
// bfs+优先队列
bool bfs()
{
priority_queue<Node> q;
for(int i = 0; i < v[0].size(); i++) // 将根节点信息加入到队列
q.push(v[0][i]);
if(cnt[0] == 0) // 如果根节点没有怪物,则把def标记为-1
{
Node t = {0, -1, 0};
q.push(t);
}
visit[0] = true; // 标记根节点已被访问
while(!q.empty())
{
Node t = q.top();
q.pop();
if(t.def == -1)
{
for(int i = 0; i < n; i++)
{
if(!visit[i] && g[t.id][i] == 1) // 遍历与该节点连通且未被访问的节点
{
visit[i] = true; // 标记节点已被访问
for(int j = 0; j < cnt[i]; j++)
q.push(v[i][j]); // 这个节点上的怪物信息都加入优先队列
if(cnt[i] == 0)
{
Node x = {i, -1, 0}; // 如果该点没有怪物,将def标记为-1
q.push(x);
}
}
}
continue;
}
if(atk > t.def)
{
atk += t.add;
if(--cnt[t.id] == 0)
{
t.def = -1;
q.push(t);
}
}
else
return false;
}
return true;
}
int main()
{
int T;
scanf("%d", &T);
while(T--)
{
init();
scanf("%d%d", &n, &m);
for(int i = 0; i < n - 1; i++)
{
int a, b;
scanf("%d%d", &a, &b);
g[a][b] = g[b][a] = 1; // 使用邻接矩阵表示树
}
scanf("%d", &atk);
for(int i = 0; i < m; i++)
{
int a, b, c;
scanf("%d%d%d", &a, &b, &c);
Node temp = {a, b, c};
v[a].push_back(temp);
cnt[a]++;
}
if(bfs())
printf("Oh yes.\n");
else
printf("Good Good Study,Day Day Up.\n");
}
return 0;
}