题目描述
竞赛代替不了战争,就像葡萄酒代替不了鲜血。 ——《光荣与梦想》
机房战争的爆发已是不可避免的,IAKIOI的字句已潜伏在地方的剪贴板里,#define main mian和#define sort random_shuffle的代码也在硬盘阴暗的角落里蠢蠢欲动,自动盗取 QQ ,Luogu 账号的软件隐没在庞大的 Windows 文件夹的迷雾中,等待着钩子函数陷阱的触发。
你深深地懂得自己身处战场中央就无法置身事外的道理,准备利用地理优势打一场漂亮的阵地战,并准备算出机房里每个位置会受到的打击以找到最安全的位置。具体地,机房是一张 n 个点, m 条边的简单图,每个点都有一个人,一个人可以机惨他身旁的所有人,若这一时刻一个人被机惨,那么下一时刻他会报复性机惨能机惨到的所有人(若一个时刻它被机惨多次只会报复一次),同时,如果编号为 i 的位置的人被机惨的次数大于等于这个位置的防御力 di, 他将因 AKIOI 而社死并退出战斗,即以后别人不会再机惨他,他也不会在下一轮报复机惨。若一开始由一号点开始机惨身边的所有人,求每个位置的被机惨次数。
输入
第一行两个整数为 n 和 m 表示机房这张图的点数和边数。
第二行 n 个整数 di 表示每个位置的防御力。
第三行到第 m+2 行,每行两个整数,表示这两个点之间有一条边。
输出
一行 n 个整数,第 i 个整数 ansi 表示编号为 i 的位置收到的攻击次数。
样例
样例输入
5 4
1 1 3 5 1
1 3
2 4
4 3
5 4
样例输出
1 1 3 2 1
提示
对10%的数据保证 n≤2, m ≤100000 di ≤10
对30%的数据保证 n≤10, m ≤100000 di ≤10
对100%的数据保证 n ≤100,m ≤100000,di ≤100
分析
BFS
从1号点开始BFS,队列中存储节点的编号以及当前的时间,并且记录下每个点的死亡时间(dead)和开始攻击的时间(st)
若当前时间>=死亡时间,已经死亡,退出战斗;否则,被攻击次数+1
若被攻击后血量为0,则记录下死亡时间
若当前时间>=开始攻击的时间,则入队
实现
void bfs(){
memset(dead,0x3f,sizeof dead);
queue<PII> q;
q.push({1,1});
st[1] = 1;
while(!q.empty()){
int u = q.front().first,t = q.front().second;
q.pop();
if(t >= dead[u]) continue;
for(int i = h[u];i != -1;i = ne[i]){
int j = e[i];
d[j]--;
if(!d[j]) dead[j] = t + 1;
if(t < dead[j]) cnt[j]++;
if(t >= st[j]){
q.push({j,t + 1});
st[j] = t + 1;
}
}
}
}
代码
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
typedef pair<int,int> PII;
const int N = 100 + 10,M = 100000 + 10;
int n,m;
int d[N],back_d[N];
int h[N],e[M * 2],ne[M * 2],idx;
int dead[N],st[N],cnt[N];
void add(int A,int B){
e[idx] = B,ne[idx] = h[A],h[A] = idx++;
}
void bfs(){
memset(dead,0x3f,sizeof dead);
queue<PII> q;
q.push({1,1});
st[1] = 1;
while(!q.empty()){
int u = q.front().first,t = q.front().second;
q.pop();
if(t >= dead[u]) continue;
for(int i = h[u];i != -1;i = ne[i]){
int j = e[i];
d[j]--;
if(!d[j]) dead[j] = t + 1;
if(t < dead[j]) cnt[j]++;
if(t >= st[j]){
q.push({j,t + 1});
st[j] = t + 1;
}
}
}
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
memset(h,-1,sizeof h);
cin >> n >> m;
for(int i = 1;i <= n;i++){
cin >> d[i];
back_d[i] = d[i];
}
for(int i = 1,a,b;i <= m;i++){
cin >> a >> b;
add(a,b),add(b,a);
}
bfs();
for(int i = 1;i <= n;i++) cout << min(back_d[i],cnt[i]) << ' ';
return 0;
}