首页 > 其他分享 >P3275 [SCOI2011] 糖果

P3275 [SCOI2011] 糖果

时间:2024-07-23 14:56:01浏览次数:13  
标签:P3275 ll back MAXN low push now 糖果 SCOI2011

原题链接

题解

缩点+差分约束,求最小值故跑最长路

无解的情况:存在正权环,由于是有向图,所以环上的元素在一个强连通分量内,判断强连通分量内存不存在有正权值的边,然后缩点,拓扑跑一圈

缩点时要一个超级源点就可以只dfs一次了

code

#include <bits/stdc++.h>
using namespace std;

#define ll long long

const ll MAXN = 100005;

vector<pair<ll, ll>> G[MAXN], E[MAXN];
ll vis[MAXN], dfn[MAXN], low[MAXN], belong[MAXN], in[MAXN], val[MAXN];
stack<ll> st;
ll cnt, num;

void dfs(ll now) {
    vis[now] = 1;
    dfn[now] = low[now] = ++cnt;
    st.push(now);

    for (auto next : G[now]) {
        ll to = next.first;
        if (!dfn[to]) {
            dfs(to);
            low[now] = min(low[now], low[to]);
        } else if (!belong[to]) {
            low[now] = min(low[now], dfn[to]);
        }
    }

    if (low[now] == dfn[now]) {
        ll x;
        num++;
        do {
            x = st.top();
            st.pop();
            belong[x] = num;
        } while (x != now);
    }
}

void solve() {
    ll n, k;
    cin >> n >> k;

    for (ll i = 1; i <= k; i++) {
        ll op, x, y;
        cin >> op >> x >> y;

        if (op == 1) {
            G[x].push_back({y, 0});
            G[y].push_back({x, 0});
        } else if (op == 2) {
            G[x].push_back({y, 1});
        } else if (op == 3) {
            G[y].push_back({x, 0});
        } else if (op == 4) {
            G[y].push_back({x, 1});
        } else {
            G[x].push_back({y, 0});
        }
    }

    for (ll i = 1; i <= n; i++) G[0].push_back({i, 1});
    dfs(0);

    bool flag = true;
    for (ll i = 1; i <= n; i++) {
        for (auto next : G[i]) {
            ll x = belong[i], y = belong[next.first];
            if (x == y && next.second != 0) {
                flag = false;
            }
            if (x != y) {
                E[x].push_back({y, next.second});
                in[y]++;
            }
        }
    }

    if (!flag) {
        cout << -1 << endl;
        return;
    }

    queue<ll> q;
    for (ll i = 1; i <= num; i++) {
        val[i] = 1;
        if (!in[i]) q.push(i);
    }

    while (!q.empty()) {
        ll now = q.front();
        q.pop();

        for (auto next : E[now]) {
            ll to = next.first;
            val[to] = max(val[to], val[now] + next.second);
            in[to]--;
            if (!in[to]) {
                q.push(to);
            }
        }
    }

    ll ans = 0;
    for(ll i = 1; i <= n; i++) {
        ans += val[belong[i]];
    }
    cout << ans << endl;
}

int main() {
    ios::sync_with_stdio(false);
    cin.tie(0);
    cout.tie(0);

    solve();
    return 0;
}

标签:P3275,ll,back,MAXN,low,push,now,糖果,SCOI2011
From: https://www.cnblogs.com/pure4knowledge/p/18318448

相关文章

  • 代码随想录算法训练营第31天 | 贪心3:134.加油站、135.分发糖果、860.柠檬水找零、406.
    代码随想录算法训练营第31天|贪心3:134.加油站、135.分发糖果、860.柠檬水找零、406.根据身高重建队列134.加油站https://leetcode.cn/problems/gas-station/description/代码随想录https://programmercarl.com/0134.加油站.html135.分发糖果https://leetcode.cn/problems......
  • C++题解(6) 信息学奥赛一本通:2069:【例2.12 】糖果游戏
    【题目描述】某幼儿园里,有5个小朋友编号为1、2、3、4、5,他们按自己的编号顺序围坐在一张圆桌旁。他们身上都有若干个糖果(键盘输入),现在他们做一个分糖果游戏。从1号小朋友开始,将自己的糖果均分三份(如果有多余的糖果,则立即吃掉),自己留一份,其余两份分给他的相邻的两个小朋友。......
  • 【题解】 [CSP-J 2021 T1] 分糖果
    题目描述题目大意给定正整数\(n\)、\(L\)、\(R\),求\(\max_{i\in\left[L,R\right]}{i\bmodn}\)。思路题目主要考察:分类讨论。众所周知,对于\(\forallx\),有$(x\bmodn)\in\left[0,n-1\right]$。可以分为两种情况讨论:如果\(\left\lfloor\frac{L......
  • leetcode 135.分发糖果
    题目:n个孩子站成一排。给你一个整数数组ratings表示每个孩子的评分。你需要按照以下要求,给这些孩子分发糖果:每个孩子至少分配到1个糖果。相邻两个孩子评分更高的孩子会获得更多的糖果。请你给每个孩子分发糖果,计算并返回需要准备的最少糖果数目。题目示例:示例1:......
  • CSP历年复赛题-P7909 [CSP-J 2021] 分糖果
    原题链接:https://www.luogu.com.cn/problem/P7909题意解读:计算L~R之间数模n的最大值。解题思路:如果你考虑枚举L~R,每个数模n,然后求max,那么就超时了,肯定有一点小技巧在里面。我们知道,一个数%n,最大值是n-1不难考虑,如果R/n和L/n的的商是一样的,而R>=L,那么说明R%n>=L%n,那么此时最大......
  • 代码随想录算法训练营第第35天 | 977.有序数组的平方1005.K次取反后最大化的数组和 、
    1005.K次取反后最大化的数组和本题简单一些,估计大家不用想着贪心,用自己直觉也会有思路。https://programmercarl.com/1005.K次取反后最大化的数组和.html自己写的时间复杂度太高,看答案优化/***@param{number[]}nums*@param{number}k*@return{number}*/varl......
  • 代码随想录算法训练营第三十五天 | 1005.K次取反后最大化的数组和 134.加油站 135.分
    1005.K次取反后最大化的数组和题目链接文章讲解视频讲解思路:  按绝对值从大到小排序  遍历数组,遇到负数,如果次数未用完就取反  最后如果剩余次数未用完且为奇数就将数组最后一个元素取反classSolution{staticboolmyCompare(constint&lhs,constint&r......
  • 【Python】练习:分糖果Ⅱ
    读题,发糖规则为逐个递增分发,发现分发的糖果成等差数列,最后的(不够继续分的)需特殊讨论。思考要怎么做——前面的完整分发轮次和后面的不完整分发轮次分开。出现新的问题,怎么知道有多少完整的轮次——row?注意,要求多少轮,不是用糖数整除人数(平均分)求出,而是用利用数列元素数整除......
  • 力扣:1103. 分糖果 II
    1103.分糖果II排排坐,分糖果。我们买了一些糖果 candies,打算把它们分给排好队的 n=num_people 个小朋友。给第一个小朋友1颗糖果,第二个小朋友2颗,依此类推,直到给最后一个小朋友 n 颗糖果。然后,我们再回到队伍的起点,给第一个小朋友 n +1 颗糖果,第二个小朋友......
  • 打卡信奥刷题(52)用Scratch图形化工具信奥P7909 [普及组] [CSP-J 2021] 分糖果
    [CSP-J2021]分糖果题目背景红太阳幼儿园的小朋友们开始分糖果啦!题目描述红太阳幼儿园有nnn个小朋友,你是其中之一。保证......