E. DeadLee 思维 贪心 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';
}

猜你喜欢

转载自www.cnblogs.com/CimonHe/p/13190841.html