【Codeforces 1369-E】DeadLee 贪心

E. DeadLee

题意

有 n 份食物,第 i 种食物有 \(w_i\) 份,有 m 个朋友,每个朋友都有两个爱吃的食物,现在可以决定朋友进来的顺序,当一个朋友进来没吃到自己喜欢的菜的时候,就会吃掉你,问你是否是安全的。如果是,输出朋友进来的顺序。

思考

刚看到这题很熟悉,之前打个人赛的时候做过一道类似的,只不过每份食物都是 1 份。

当时是用的最小生成树,被上题影响了思路,首先在想最小生成树,后来感觉这怎么构造?

优先用份数为 0 的,向外连边,但是如果没有或者所有的菜的份数初始都很大,这该怎么搞?

后来想到用份数足够所有人吃的向外连边,感觉不太行。就GG了。

题解

如果食物 i 足够所有的朋友吃,就把所有想吃食物 i 的朋友放到最后,并且另一种食物的需求量-1,这样就会继续产生新的够吃的食物,如果刚开始所有的食物都不够吃,那么就危险了。

代码

#include <bits/stdc++.h>
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long ll;
const int mod = 1e9 + 7;
const int inf = 0x3f3f3f3f;
const int N = 2e6+10;

vector<pair<int,int> > vec[N];
int w[N], s[N], dis[N], sign[N];

int main()
{
    int n, m;
    scanf("%d%d", &n, &m);
    for(int i = 1; i <= n; i++)
        scanf("%d", &w[i]);
    for(int i = 1; i <= m; i++)
    {
        int u, v;
        scanf("%d%d", &u, &v);
        s[u]++, s[v]++;
        vec[u].pb(make_pair(v, i));
        vec[v].pb(make_pair(u, i));
    }
    queue<int> q;
    for(int i =1 ; i <= n; i++)
    {
        dis[i] = w[i] - s[i];
        if(dis[i] >= 0)
            q.push(i);
    }
    stack<int>ans;
    int num = 0;
    while(!q.empty())
    {
        num++;
        int now = q.front();
        q.pop();
        for(auto temp : vec[now])
        {
            if(!sign[temp.second])
            {
                dis[temp.first]++;
                if(dis[temp.first] == 0){
                    q.push(temp.first);
                }
                ans.push(temp.second);
                sign[temp.second]=1;
            }
        }
    }
    if(num != n)
        printf("DEAD\n");
    else
    {
        printf("ALIVE\n");
        while(!ans.empty())
        {
            printf("%d ", ans.top());
            ans.pop();
        }
    }
    printf("\n");
    return 0;
}
/*
3 2
1 1 0
1 2
1 3
*/
posted @ 2020-07-15 21:03  Valk3  阅读(103)  评论(0编辑  收藏  举报