https://codeforces.ml/contest/1369/problem/E
题目大意:
有m道菜(每道菜有ai个),n个人,每个人有两个要吃的菜,问能否安排一个合法的吃饭顺序,使得每个人都至少有一道菜可以吃
题目思路:
想了一天唉..
经过多方对比,发现这个思路,时间和空间都是最优的,并且比较好理解,就写一下当前的思路吧。
倒着贪心
就考虑最后一个应该放什么
最后一个放的应该满足一个要求:即就算前面都吃了属于他的菜,他依然可以有菜吃
所以统计每道菜的总需求量(w[i]),与当前每道菜的供给量作为对比(ai)
如果 w[i] <= a[i] ,那么表示吃这个菜的人,无论如何都有菜吃。
那么吃这第i道菜的人,就完全可以不吃另一道菜了,即另一道菜需求量减1
如果有新的w[i] <= a[i] 那么就再倒着吃这道菜 按照之前的方式进行更新
扫描二维码关注公众号,回复:
11436916 查看本文章
如果存在 没有w[i] <= a[i] 即 剩下的所有菜需求量都大于供给量 那么一定不能成功分配了(因为至少每个人都要吃一个菜嘛)
Code:
/*** keep hungry and calm CoolGuang!***/
#include <bits/stdc++.h>
#pragma GCC optimize(3)
//#pragma GCC optimize("Ofast","unroll-loops","omit-frame-pointer","inline")
#include<stdio.h>
#include<queue>
#include<algorithm>
#include<string.h>
#include<iostream>
#define debug(x) cout<<#x<<":"<<x<<endl;
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll INF=2e18;
const int maxn=1e6+6;
const int mod=1e9+6;
const double eps=1e-15;
inline bool read(ll &num)
{char in;bool IsN=false;
in=getchar();if(in==EOF) return false;while(in!='-'&&(in<'0'||in>'9')) in=getchar();if(in=='-'){ IsN=true;num=0;}else num=in-'0';while(in=getchar(),in>='0'&&in<='9'){num*=10,num+=in-'0';}if(IsN) num=-num;return true;}
ll n,m,p;
ll num[maxn];
ll w[maxn];
vector<int>ans;
vector<pair<int,int>>v[maxn];
int vis[maxn];
int main()
{
memset(vis,0,sizeof(vis));
read(n);read(m);
for(int i=1;i<=n;i++) read(num[i]);
for(int i=1;i<=m;i++){
ll x,y;read(x);read(y);
w[x]++;w[y]++;
v[x].push_back({y,i});
v[y].push_back({x,i});
}
queue<int>q;
for(int i=1;i<=n;i++){
if(w[i] <= num[i]) q.push(i);
}
while(!q.empty()){
int u = q.front();q.pop();
for(auto x:v[u]){
if(!vis[x.second]){
vis[x.second] = 1;
ans.push_back(x.second);
if(--w[x.first]<=num[x.first]){
q.push(x.first);
}
}
}
}
if(ans.size()<m) printf("DEAD\n");
else {
printf("ALIVE\n");
reverse(ans.begin(),ans.end());
for(int x:ans){
printf("%d ",x);
}
printf("\n");
}
return 0;
}
/**
5
7 3
1 2 3 4 5 6 7
1 2 4
**/