Codeforces Round #652 (Div. 2) E. DeadLee 思维 贪心 详解
原题面:

题目大意:
李准备了n种菜,每种菜有对应数量wi(可能为0),他有m个朋友,每个朋友喜欢吃两种菜x,y,只要看到有x菜存在,就必吃一盘,看到有y菜存在,也必吃一盘,每个朋友都必须至少吃一盘菜,不然就会把李吃掉,请你判断李是否会被吃掉。
思路:
贪心,先算出每种菜对应的朋友数,如果该种菜的数量大于需求,那么吃该菜的朋友就放后面,因为已经保证其能吃到菜,然后将吃该菜的朋友喜欢吃的另一个菜减一,重复上述过程。值得注意的是,这里我们用优先队列存储某菜的数量减需求量。
详细见代码,有我的详细注释,这是cf的官方代码,按照自己的码风整理了一下。
#include <bits/stdc++.h>
#define ll long long
#define fr first
#define sc second
#define pii pair<int, int>
#define all(v) v.begin(), v.end()
using namespace std;
const int MN = 2e5+7;
//mark[i]标记人 表示第i个朋友不需要再吃菜了
int x[MN], y[MN], s[MN], w[MN], mark[MN], colmark[MN];//colmark[i]标记菜 表示第i个菜已经不需要被吃了
vector<int> v[MN], a;//v [k] :吃第k盘菜的有哪几个朋友 a 最终输出的答案数组 也就是叫朋友的顺序
priority_queue<pii, vector<pii>, greater<pii>> pq;//优先队列 以s[i]-w[i]小为first优先 second为i即第i盘菜
signed main(){
ios::sync_with_stdio(false);
cin.tie();
cout.tie();
int n, m;
cin >> n >> m;
for(int i = 1; i <= n; i++)
cin >> w[i];
for(int i = 0; i < m; i++)
{
cin >> x[i] >> y[i];
s[x[i]]++;
s[y[i]]++;
v[x[i]].push_back(i);
v[y[i]].push_back(i);
}
for(int i = 1; i <= n; i++)
{
if(s[i])
pq.push({max(0, s[i]-w[i]), i});
else
colmark[i] = 1;
}
while(pq.size())
{
auto q = pq.top();
pq.pop();
if(q.fr != max(0, s[q.sc]-w[q.sc])) //把过时的给筛掉
continue;
if(q.fr > 0) //如果对菜的需求大于菜的数量
{
cout << "DEAD\n";
exit(0);
}
int id = q.sc;//id:菜的序号
vector<int> wt;//存下所有保证吃到第id个菜的朋友的另一个菜
for(auto u : v[id])//依次取出吃该菜的朋友
{
if(mark[u])//吃这个菜的朋友u已经保证吃过一个菜了 滚一边去
continue;
a.push_back(u);//把这些菜放进最终的答案数组a
if(x[u] == id)
swap(x[u], y[u]);
if(!colmark[x[u]])//如果第x[u]个菜还有人吃
wt.push_back(x[u]);
mark[u] = 1;//标记该朋友u已经能保证吃到一个菜了
}
sort(all(wt));//给wt数组排个序 目的就是将相同的菜聚到一起
for(int i = 0; i < wt.size(); i++)
{
s[wt[i]]--;//需要吃第wt[i]个菜的朋友又少了一个
if(i == wt.size()-1 || wt[i+1] != wt[i])//直到扫完wt数组中某序号的所有菜
{
if(s[wt[i]])
{
if(max(0, s[wt[i]]-w[wt[i]]) == 0)//如果需要该wt[i]菜的人数少于可供选择的菜数
colmark[wt[i]] = 1; //将colmark数组中该菜置为 1 表示该菜已经没人需要选了
pq.push({max(0, s[wt[i]]-w[wt[i]]), wt[i]}); //继续将该菜放进优先队列
}
}
}
}
cout << "ALIVE\n";
for(int i = 0; i < a.size()/2; i++)
swap(a[i], a[a.size()-i-1]);// 弄成逆序
for(auto u : a)
cout << u+1 << ' ';//依次输出答案数组
cout << '\n';
}

浙公网安备 33010602011771号