Codeforces Round #652 (Div. 2) E. DeadLee

题目链接:https://codeforces.com/contest/1369/problem/E

题意:Lee邀请m位朋友来家里恰晚饭,每个朋友有两个喜欢吃的菜,轮流去厨房取菜,如果一个人进厨房的时候两个喜欢的菜都在,则会拿两个菜,只有一个喜欢的菜就拿一个,一个都没有的话就会把Lee吃掉,朋友进厨房的顺序由Lee决定,如果Lee能活下去就输出ALIVE并输出朋友进厨房的顺序,反之输出DEAD。

分析:根据贪心的思想,要尽可能的让更多的的人进去的时候只能吃一道菜。假设有b[i]个人喜欢吃第i道菜,如果b[i]<=w[i]的话,那么他们不管什么时候进厨房都是能吃到自己喜欢吃的菜的,所以让这些人在最后进厨房。这些人当中喜欢吃的第二道菜(假设这道菜为b[j])有两种情况,①b[j] <= w[j],那么和上面的一样,往后排。②b[j] > w[j],因为喜欢吃这道菜的人的另一个喜欢吃的菜已经供大于需了,所以这第二道菜他是可吃可不吃的,此时我们将第二道菜的需求b[j]-1再判断此时b[i]和w[i]的关系,如果b[j]==w[j],则说明贪心成功,喜欢吃b[j]这道菜的朋友也可以吃到自己喜欢吃的菜而不用吃Lee了。

#include<bits/stdc++.h>
#include<vector>
#include<map>
#include<queue>
#define LL long long
#define INF (LL)1<<63-1
#define MOD 1000000007
using namespace std;
const int N = 2e5 + 105;
int w[N], b[N], vis[N];
int main()
{
    int n, m, x, y;
    scanf("%d%d", &n, &m);
    for(int i = 0;i < n;i++)
        scanf("%d", &w[i]);
    vector<pair<int, int>> a[n];
    for(int i = 0;i < m;i++)
    {
        scanf("%d%d", &x, &y);
        x--,y--;
        a[x].emplace_back(y, i);
        a[y].emplace_back(x, i);
        b[x]++, b[y]++;
    }
    queue<int> q;
    for(int i = 0;i < n;i++)
    {
        if(w[i] >= b[i])
            q.push(i);
    }
    vector<int> ans;
    while(!q.empty())
    {
        int tem = q.front();
        q.pop();
        for(auto it: a[tem])
        {
            int type = it.first;
            int pos = it.second;
            if(vis[pos]) continue;
            vis[pos] = 1;
            ans.push_back(pos);
            if(--b[type] == w[type])
                q.push(type);
        }
    }
    if(ans.size() < m) printf("DEAD
");
    else
    {
        printf("ALIVE
");
        for(int i = m-1;i >= 0;i--)
            printf("%d ", ans[i]+1);
        printf("
");
    }
    return 0;
}
原文地址:https://www.cnblogs.com/Mamba0Z/p/13218294.html