CF1369E- DeadLee

题意:

\(Lee\) 的厨房中有 \(n\) 道菜,每道菜的数量为 \(w[i]\) ,现在 \(Lee\) 邀请 \(m\) 个朋友,每个朋友都有最爱吃的两道菜 \(x[i]\)\(y[i]\) ,当朋友 \(i\) 来到 \(Lee\) 家后,会选择吃掉 \(x[i]\)\(y[i]\) 各一份,如果 \(x[i]\) 没有了的话,那么他只会选择吃掉一份 \(y[i]\),如果 \(y[i]\) 没有了的话同理,但是如果 \(x[i]\)\(y[i]\) 同时没有的话,这个朋友就会吃掉 \(Lee\),问 \(Lee\) 能否安排一个合适的顺序以保证存活,输出这个顺序。

分析:

\(sum[i]\) 表示要吃第 \(i\) 种菜的人数,当 \(sum[i]\leq w[i]\),表示这 \(sum[i]\) 个人都可以吃菜。那么,就可以把这些人,放在后面来吃。如果 \(\forall sum[i]\),都有 \(sum[i]>w[i]\),则表示没有解。因此,从满足 \(sum[i]\leq w[i]\) 的食物出发,类似于拓扑排序不断向队列里面加满足要求的食物,直到可以吃到食物的人数为 \(m\)

代码:

#include <bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=2e5+5;
typedef pair<int,int>pii;
int w[N],sum[N];
vector<pii>food[N];
int n,m;
queue<int>que;
stack<int>ans;
bool vis[N];
bool solve()
{
    for(int i=1;i<=n;i++)
    {
        if(sum[i]<=w[i])
            que.push(i);
    }
    while(!que.empty())
    {
        int t=que.front();
        que.pop();
        for(int i=0;i<food[t].size();i++)
        {
            int a=food[t][i].first;
            int b=food[t][i].second;
            if(vis[b]) continue;
            ans.push(b);
            vis[b]=1;
            if(--sum[a]<=w[a]) que.push(a);
        }
    }
    return ans.size()==m;
}
int main()
{
    int x,y;
    scanf("%d%d",&n,&m);
    for(int i=1;i<=n;i++)
        scanf("%d",&w[i]);
    for(int i=1;i<=m;i++)
    {
        scanf("%d%d",&x,&y);
        sum[x]++,sum[y]++;
        food[x].pb(make_pair(y,i));
        food[y].pb(make_pair(x,i));
    }
    if(solve())
    {
        printf("ALIVE\n");
        while(!ans.empty())
        {
            int t=ans.top();
            ans.pop();
            printf("%d%c",t,ans.empty()?'\n':' ');
        }
    }
    else printf("DEAD\n");
    return 0;
}

参考博客

posted @ 2020-06-26 08:41  xzx9  阅读(210)  评论(0编辑  收藏  举报