题目链接:Smallest Minimum Cut
题目大意:给你一张图,问最小边数的最小割是多少
题目思路:跑网络流,最小流可能会有很多歌,所以我们需要做的是扩大每条边的容量,我们把容量扩大m+1倍,因为我们扩展后会把每条边的容量再加一,最多m条边,所以扩大m+1是没有问题的,这样扩展后边容量其实没变化,但是最后加的1对边的个数形成了冲击,最后我们找出加了多少个一的最小割就好了,也就是对(m+1)取余就好了
#include <map>
#include <set>
#include <cmath>
#include <queue>
#include <stack>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
using namespace std;
typedef long long ll;
const int MAXN = 1e4+10;
const int MAXM = 1e4+10;
const int INF = 0x3f3f3f3f;
struct Edge{
int from, to, cap, flow, next;
}edge[MAXM];
int dist[MAXN], vis[MAXN], cur[MAXN], top, head[MAXN];
int n, m;
int sumflow;
int sink;
void init(){
top = 0;
memset(head, -1, sizeof(head));
}
void addedge(int u, int v, int w){
Edge E1 = {u, v, w, 0, head[u]};
edge[top] = E1;
head[u] = top++;
Edge E2 = {v, u, 0, 0, head[v]};
edge[top] = E2;
head[v] = top++;
}
bool BFS(int start, int End){
queue<int> Q;
memset(dist, -1, sizeof(dist));
memset(vis, 0, sizeof(vis));
while(!Q.empty()) Q.pop();
Q.push(start);
vis[start] = 1;
dist[start] = 0;
while(!Q.empty()){
int u = Q.front();
Q.pop();
for(int i = head[u]; i != -1; i = edge[i].next){
Edge E = edge[i];
if(!vis[E.to] && E.cap > E.flow){
vis[E.to] = 1;
dist[E.to] = dist[u] + 1;
if(E.to == End) return true;
Q.push(E.to);
}
}
}
return false;
}
int DFS(int x, int a, int End){
if(x == End || a == 0) return a;
int flow = 0, f;
for(int& i = cur[x]; i != -1; i = edge[i].next){
Edge& E = edge[i];
if(dist[E.to] == dist[x]+1 && (f = DFS(E.to, min(a, E.cap-E.flow), End)) > 0){
E.flow += f;
edge[i^1].flow -= f;
flow += f;
a -= f;
if(a == 0) break;
}
}
return flow;
}
int Dinic(int start, int End){
int flow = 0;
while(BFS(start, End)){
memcpy(cur, head, sizeof(head));
flow += DFS(start, INF, End);
}
return flow;
}
int main(){
int T,u,v,w,s,t;
scanf("%d",&T);
while(T--){
init();
scanf("%d%d",&n,&m);
scanf("%d%d",&s,&t);
int mm = m;
while(mm--){
scanf("%d%d%d",&u,&v,&w);
addedge(u,v,w*(m+1)+1);
}
printf("%d\n",Dinic(s,t)%(m+1));
}
return 0;
}