题意:
(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
");
while(!ans.empty())
{
int t=ans.top();
ans.pop();
printf("%d%c",t,ans.empty()?'
':' ');
}
}
else printf("DEAD
");
return 0;
}