Gym - 101667 E How Many to Be Happy?(最小割)

題目鏈接

題意:給一個連通無向圖,對於圖中的每條邊,這條邊可能在某一顆最小生成樹上,如果在稱爲happy的邊,否則稱爲unhappy的邊。對於unhappy的邊,總是可以刪掉一些邊使得它變成happy的邊,設h(e)爲使e變成happy最少需要刪的邊數,定義happy邊的h值爲0,讓你求所有邊的h值之和。

題解:我們知道要是一個邊沒有在最小生成樹裏面,能對他造成影響的只有邊權比它小的邊(在構成最小生成樹的過程中就是優先選邊權小的邊),所以我們在考慮要讓這條邊到最小生成樹裏面,就應該使比它邊權小的邊不連通,這樣要是想選比它邊權小的就必定要選它了,所以我們枚舉每條邊,讓邊權比它小的邊連成一個圖,起點和終點就是這條邊的兩個端點,現在要計算刪除最少的邊讓這個圖不連通,這就是最小割了。

PS:這裏有個小疑問,爲什麼在建圖的過程中反向邊也要有流,望大佬提醒。

#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#include<stack>
#include<string>
#include <unordered_set>

const int mod = 998244353;
const int maxn = 5e5 + 5;
const int inf = 1e9;
const long long onf = 1e18;
#define me(a, b) memset(a,b,sizeof(a))
#define lowbit(x) x&(-x)
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define PI 3.14159265358979323846
typedef long long ll;
typedef unsigned long long ull;
using namespace std;
int n, m;
int head[maxn], cur[maxn], tot;
int depth[maxn];
int st, ed;

struct Node {
    int u, v, val;
} a[maxn];
struct node {
    int v, next, flow;
} tree[maxn];

void add_edge(int u, int v, int flow) {
    tree[tot] = node{v, head[u], flow};
    head[u] = tot++;
}

void ins(int u, int v, int flow) {
    add_edge(u, v, flow);
    add_edge(v, u, flow);
}

bool bfs() {
    for (int i = 1; i <= n; i++)
        depth[i] = -1;
    depth[st] = 1;
    queue<int> q;
    q.push(st);
    while (!q.empty()) {
        int u = q.front();
        q.pop();
        for (int i = head[u]; i != -1; i = tree[i].next) {
            int v = tree[i].v, flow = tree[i].flow;
            if (flow && depth[v] == -1) {
                depth[v] = depth[u] + 1;
                q.push(v);
            }
        }
    }
    return depth[ed] != -1;
}

int dfs(int u, int flow) {
    if (u == ed)
        return flow;
    int used = 0;
    for (int i = cur[u]; i != -1; i = tree[i].next) {
        int v = tree[i].v, tempflow = tree[i].flow;
        if (flow && depth[v] == depth[u] + 1) {
            int Min = dfs(v, min(flow, tempflow));
            if (Min) {
                flow -= Min, used += Min;
                tree[i].flow -= Min;
                tree[i ^ 1].flow += Min;
            }
        }
    }
    return used;
}

int Dinic() {
    int sum = 0;
    while (bfs()) {
        for (int i = 1; i <= n; i++)
            cur[i] = head[i];
        sum += dfs(st, inf);
    }
    return sum;
}

void init() {
    for (int i = 1; i <= n; i++)
        head[i] = -1;
    tot = 0;
}

void work() {
    scanf("%d%d", &n, &m);
    for (int i = 1; i <= m; i++)
        scanf("%d%d%d", &a[i].u, &a[i].v, &a[i].val);
    int ans = 0;
    for (int i = 1; i <= m; i++) {
        init();
        for (int j = 1; j <= m; j++) {
            if (a[j].val < a[i].val)
                ins(a[j].u, a[j].v, 1);
        }
        st = a[i].u, ed = a[i].v;
        ans += Dinic();
    }
    printf("%d\n", ans);
}

int main() {
#ifndef ONLINE_JUDGE
    //freopen("1.in", "r", stdin);
#endif
    int t = 1, Case = 1;
    // cin >> t;
    while (t--) {
        //  printf("Case %d: ", Case++);
        work();
    }
    return 0;
}

 


 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章