題目鏈接
題意:給一個連通無向圖,對於圖中的每條邊,這條邊可能在某一顆最小生成樹上,如果在稱爲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;
}