キャンディ「SCOI2011」微分制約

[タイトル]説明
幼稚園があります\(N \) 2人の子供、\(\ lxhgww)教師は今、これらの子供たちのお菓子に割り当てる、キャンディが割り当てられるすべての子供が必要です。しかし、そこに子供たちに嫉妬は、常に彼以上に割り当てられた赤いキャンディーを望んでいないなど暁明など、いくつかの要求を、前方に置くがあるので、ときお菓子の配布、\(lxhgww \)子供満たすために必要な\を(K \ )要件。幼稚園キャンディーは常に限られている、\(\ lxhgww)は、彼はすべての子供がお菓子を割り当てることができるようにするためには、少なくとも1個のお菓子を準備する必要がどのくらいかを知りたい、と子供たちはすべての要件を満たしています。

フェアリー幼稚園

[入力形式
入力二つの整数の最初の行の\(N、K \)
これらの点の関係を示す次のK線は、満たされる必要があり、行ごとに3桁、\(X、A、B \)
場合\は(X- = 1 \)を表し、\(\)の子供はキャンディと割り当てられなければならない\(B \)を割り当てられたキャンディ子供の複数として、
もし\(X-2 = \)を表します\(\)キャンディを割り当て子供が最初よりも小さくなければならない\(B \)子供のキャンディに割り当てられた番号;
場合(X- = 3 \)\を表す\(\)子が割り当てられなければならないのキャンディー以上であること\(B \)子供のキャンディに割り当てられた番号、
場合\(X- = 4 \。)を表し、\(\)のキャンディを割り当て子供が最初よりも大きくなければならない\(B \)サブ子供番目キャンディに、
場合\(5 X- = \。)を表し、\(\)キャンディは以上の子に割り当てなければならない\(Bの\)を子供のお菓子を割り当てます。

[]出力形式の
出力が示す行\(lxhgwwを\)あなたは子供たちのすべての要件を満たすことができない場合は、教師のお菓子の数は少なくとも、準備する必要があり、それが出力される\(--1 \)

\(N \の当量100000 \) \(K \の当量100000 \) \(1 \当量X \当量5 \) \(1 \当量のA、Bの\当量N \)

微分制約テンプレートのタイトル

差動制約について
あなたは:問題のクラスを解決するための差動制約システム\(\ N-)形式の目\(XY \ルZ \)ソリューションと可解のセットが資格不平等か、求めている
。このため問題の種類は、それぞれについて処理される\(XY \ルZの\)もYからXまで、Zは右側有向エッジです。フォームの場合\(XY \ GE Zが\)不等式は、に変換することができる\(YX \ル-z \)側を接続します。
所与のグループの場合\(X = Yの\)式は、に変換することができる\(0 \ルXY \ル 0 \) 、すなわち偶数\(X、Yの\)エッジの重みは、間にある\(0 \)無向エッジ
最後に、\(0 \)は、各エッジ点にも重量ドット\(0 \)有向エッジ、または少なくともする場合のそれぞれの数であれば\(1 \)のも右側\(1 \)サイド。
次にから\(0 \)ドットSPFAを実行し始め、負リング溶液、または存在しない場合\(DIS [1] \)する\(DIS [N] \)これは、ソリューションの対応するセットです。

[コード]

#include <iostream>
#include <cstdio>
#include <queue>
#include <cstring>
#define re register
using namespace std;
typedef long long ll;

ll n, m, sum;
ll head[1000005], to[1000005], pre[1000005], val[1000005], len;
ll dis[1000005], cnt[1000005];
bool vis[1000005];

ll read() {
    ll ret = 0;
    char ch = getchar();
    while (ch < '0' || ch > '9') ch = getchar();
    while (ch >= '0' && ch <= '9') {
        ret = ret * 10 + ch - '0';
        ch = getchar();
    }
    return ret;
}

void insert(ll u, ll v, ll w) {
    len++;
    to[len] = v, pre[len] = head[u], val[len] = w, head[u] = len;
}

queue<ll> q;

bool SPFA() {
    
    q.push(0);
    vis[0] = 1;
    while (!q.empty()) {
        ll c = q.front();
        q.pop();
        vis[c] = 0;
        if (cnt[c] == n - 1) return false;
        cnt[c]++;
        for (re ll i = head[c]; i != 0; i = pre[i]) {
            if (dis[c] + val[i] > dis[to[i]]) {
                dis[to[i]] = dis[c] + val[i];
                // cnt[to[i]] = cnt[c] + 1;
                // if (cnt[to[i]] > n) {
                //  return false;
                // }
                if (!vis[to[i]]) {
                    vis[to[i]] = 1;
                    q.push(to[i]);
                }
            }
        }
    }
    return true;
}

int main() {
    n = read(), m = read(); 
    for (re ll i = 1; i <= m; i++) {
        ll ch, a, b;
        ch = read();
        a = read(), b = read();
        switch (ch) {
            case 1: insert(b, a, 0), insert(a, b, 0); break;
            case 2: {
                insert(a, b, 1); 
                if (a == b) {
                    cout << -1 << endl;
                    return 0;
                }
                break;
            }
            case 3: insert(b, a, 0); break;
            case 4: {
                if (a == b) {
                    cout << -1 << endl;
                    return 0;
                }
                insert(b, a, 1); 
                break;
            }
            case 5: insert(a, b, 0); break;
        }
    }
    for (re ll i = n; i >= 1; i--) {
        insert(0, i, 1);
    }
    q.push(0);
    vis[0] = 1;
    while (!q.empty()) {
        ll c = q.front();
        q.pop();
        vis[c] = 0;
        for (re ll i = head[c]; i != 0; i = pre[i]) {
            if (dis[c] + val[i] > dis[to[i]]) {
                dis[to[i]] = dis[c] + val[i];
                if (!vis[to[i]] && cnt[to[i]] < n) {
                    vis[to[i]] = 1;
                    cnt[to[i]]++;
                    q.push(to[i]);
                } else if (cnt[to[i]] >= n) {
                    cout << -1 << endl;
                    return 0;
                }
            }
        }
    }
    for (int i = 1; i <= n; i++) sum += dis[i];
    cout << sum << endl;
    return 0;
}

おすすめ

転載: www.cnblogs.com/ak-dream/p/AK_DREAM10.html