CF1369E. DeadLee 思维

46 篇文章 1 订阅
34 篇文章 0 订阅

Link
思维,贪心,拓扑排序 2400

题意

n n n种菜,每种菜都有 w i w_i wi碟,你有 m m m个朋友,每个朋友都有两种喜欢的菜,你按照某个排序让朋友一个一个来吃菜,如果现在桌上有这个朋友喜欢的菜,他就会每种都吃一碟,但是如果两种菜都没了,你就会死。问你最后你会不会死,如果不会输出这个排序。

思路

显然,如果第 i i i 种菜的需求不大于 w i w_i wi,那么吃这种菜的人一定能吃到,我们贪心地把这些人往后排。同时对于这些人,它们已经吃了一种菜 i i i了,那么对于他们喜欢的另一种菜 j j j,需求就会少1。发现这一过程类似于拓扑排序,考虑建一张图:
n n n个点分别为每个菜,而 2 ∗ m 2*m 2m条边 < u , v > <u,v> <u,v>分别连接每个朋友喜欢的两种菜 u , v u, v u,v,并分别用 w [ i ] , i n [ i ] w[i],in[i] w[i]in[i]表示第 i i i个菜有多少碟以及需求量,容易发现需求量和拓扑排序里的入度很像。起初把需求量不超过碟数的点加入队列,然后每次将队首元素与其到达的点 v v v 入度减1,若 i n [ v ] = = w [ v ] in[v] == w[v] in[v]==w[v]则加入队列。同时将这条边所代表的朋友加入栈(无论是否in[v] == w[v]),最后判断栈中元素数量是否为m即可。

代码

int n, m;
int w[maxn];
vector<pair<int, int> > e[maxn];
int in[maxn];
bool vis[maxn];
queue<int> q;
stack<int> ans;
void solve() {
    cin >> n >> m;
    for(int i = 1; i <= n; i++) cin >> w[i];
    for(int i = 1; i <= m; i++) {
        int x, y;
        cin >> x >> y;
        e[x].pb(make_pair(y,i));
        e[y].pb(make_pair(x,i));
        in[x]++; in[y]++;
    }
    for(int i = 1; i <= n; i++) {
        if(in[i] <= w[i]) q.push(i);
    }
    while(!q.empty()) {
        int x = q.front();
        q.pop();
        for(auto i : e[x]) {
            int to = i.first;
            int a = i.second;
            in[to]--;
            if(!vis[a])
            {
                ans.push(a);
                vis[a] = 1;
            }
            if(in[to] == w[to]) 
                q.push(to);
        }
    }
    if(ans.size() < m) {
        cout << "DEAD\n";
        return;
    }
    cout << "ALIVE\n";
    while(!ans.empty()) {
        cout << ans.top() << ' ';
        ans.pop();
    }
    cout << endl;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值