HDU 6445(競賽圖 + 網絡流)

題意: 給出一個n(<=200)個節點的競賽圖, 計算圖中所給的ans.

枚舉四元組(a, b, c, d) ,
四元組一共有3種情況:
1. 成環 ans ++, 也就是有向環組成的。
2. 不成環, ans不變, 也就是說有且僅有一個點的出度爲2
3. 不成換,ans– , 擁有兩個點出度爲2.

一共有A(n, 4)種組合, 枚舉每一個度數>=2的點,對於其出度的點,有C(deg, 2)種選法, 剩下一個點在(n - 3)種選擇。
最後要求的就是A(n,4)A(deg,2)(n3)4

實際上要找的就是 C(deg,2)

我們考慮用費用流來計算上式的最小值。

建立兩列點, 左邊一列代表方向不確定的邊, 右邊代表1-n節點, 左邊會拉出兩條邊連向右邊的點,源連左邊,右邊連匯,如果我們求的是 deg , 這道題就已經結束了。

現在改成C(deg,2) , 我們一定做過邊權和n^2 有關的那道題(沒有請自己翻紫書),這題如是。

貼簡要代碼:

#include <bits/stdc++.h>
const int N = 1e3+9;
using namespace std;
using ll = long long;
int n, deg[N], ecnt[N];
char s[202][202];
namespace MCMF { ... }
void init() { memset(ecnt, 0, sizeof ecnt); memset(deg, 0, sizeof deg); MCMF::init(); }

int main() {
    int t; scanf("%d", &t);
    while(t--) {
        init(); scanf("%d", &n); int tot = n+1; ll tmp = 0;
        for (int i = 1; i <= n; i++) {
            scanf("%s", s[i]+1);
            for (int j = 1; j <= n; j++) {
                if(s[i][j] == '1') deg[i]++;
                else if(s[i][j] == '2' && i < j) {
                    ecnt[i] ++; ecnt[j] ++;
                    MCMF::add(tot, i, 1, 0); MCMF::add(tot, j, 1, 0); tot++;
                }
            }
        }
        MCMF::s = n+tot, MCMF::t = n+tot+1;
        for (int i = n+1; i < tot; i++) MCMF::add(MCMF::s, i, 1, 0);
        for (int i = 1; i <= n; i++) {
            int tt = deg[i];
            tmp += tt*(tt-1)/2;
            for (int j = 0; j < ecnt[i]; j++) MCMF::add(i, MCMF::t, 1, tt++);
        }
        MCMF::MCMF(); tmp += MCMF::ans;
        tmp = n*(n-1)*(n-2)*(n-3) - tmp * (n - 3) * 8;
        printf("%lld\n", tmp);
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章