Smallest Minimum Cut
Time Limit: 2000/2000 MS (Java/Others) Memory Limit:65535/32768 K (Java/Others)
Total Submission(s): 110 Accepted Submission(s): 33
Problem Description
Consider a network G=(V,E) with source s and sinkt. An s-t cut isa partition of nodes setV intotwo parts such thats andt belong todifferent parts. The cut set is the subset ofE with all edgesconnecting nodes in different parts. A minimum cut is the one whose cut set hasthe minimum summation of capacities. The size of a cut is the number of edgesin the cut set. Please calculate the smallest size of all minimum cuts.
Input
The input contains several test cases and the first line is the total number ofcasesT (1≤T≤300).
Each case describes a network G, andthe first line contains two integersn (2≤n≤200) andm (0≤m≤1000) indicating thesizes of nodes and edges. All nodes in the network are labelled from 1 to n.
The second line contains two different integers s andt (1≤s,t≤n) correspondingto the source and sink.
Each of the next m linescontains three integersu,v andw (1≤w≤255) describing adirected edge from nodeu tov with capacityw.
Output
For each test case, output the smallest size of all minimum cuts in a line.
Sample Input
2
4 5
1 4
1 2 3
1 3 1
2 3 1
2 4 1
3 4 2
4 5
1 4
1 2 3
1 3 1
2 3 1
2 4 1
3 4 3
Sample Output
2
3
【题意】
给出一个图,求出该图最小割中边数最少的边数是多少。
【思路】
取一个mod,建边的时候每条边权设为w*mod+1,那就跑一下最小割的模板就可以了。这样得到的最大流为maxflow/mod,最小割中的最小边数为maxflow%mod。
那么为什么可以这样做呢?
因为我们边权里的w*mod+1,那个加一就相当于是边数,那么在最小割相同的情况下,边数较小的最小割的maxflow较小。这样就能求出最小割了。
需要注意的是这里的mod应该取得大一些,防止边数增大到一定程度产生“进位”,影响最小割的结果。
#include <cstdio>
#include <vector>
#include <queue>
#include <cstring>
#include <algorithm>
using namespace std;
#define mst(a,b) memset((a),(b),sizeof(a))
#define rush() int T;scanf("%d",&T);while(T--)
typedef long long ll;
const int maxn = 205;
const ll mod = 10005;
const int INF = 0x3f3f3f3f;
int n,m;
struct Edge
{
int from,to;
ll cap,flow;
Edge(int u,int v,ll c,ll f):from(u),to(v),cap(c),flow(f) {}
};
struct Dinic
{
int n,m,s,t;
vector<Edge>edges;
vector<int>G[maxn];
bool vis[maxn];
int d[maxn];
int cur[maxn];
void init(int n)
{
for (int i=0; i<=n; i++) G[i].clear();
edges.clear();
}
void AddEdge(int from,int to,int cap)
{
edges.push_back(Edge(from,to,cap,0));
edges.push_back(Edge(to,from,0,0));
m=edges.size();
G[from].push_back(m-2);
G[to].push_back(m-1);
}
bool BFS()
{
memset(vis,0,sizeof(vis));
queue<int>Q;
Q.push(s);
d[s]=0;
vis[s]=1;
while (!Q.empty())
{
int x=Q.front();
Q.pop();
for (int i=0; i<(int)G[x].size(); i++)
{
Edge& e=edges[G[x][i]];
if (!vis[e.to] && e.cap>e.flow)
{
vis[e.to]=1;
d[e.to]=d[x]+1;
Q.push(e.to);
}
}
}
return vis[t];
}
ll DFS(int x,ll a)
{
if (x==t || a==0) return a;
ll flow=0,f;
for (int& i=cur[x]; i<(int)G[x].size(); i++)
{
Edge& e=edges[G[x][i]];
if (d[x]+1==d[e.to] && (f=DFS(e.to,min(a,e.cap-e.flow)))>0)
{
e.flow+=f;
edges[G[x][i]^1].flow-=f;
flow+=f;
a-=f;
if (a==0) break;
}
}
return flow;
}
ll Maxflow(int s,int t)
{
this->s=s;
this->t=t;
ll flow=0;
while (BFS())
{
memset(cur,0,sizeof(cur));
flow+=DFS(s,INF);
flow%=mod;
}
return flow;
}
} A;
int main()
{
int ss,tt;
int u,v,w;
rush()
{
scanf("%d%d",&n,&m);
scanf("%d%d",&ss,&tt);
A.init(n);
for(int i=1;i<=m;i++)
{
scanf("%d%d%d",&u,&v,&w);
A.AddEdge(u,v,(ll)w*mod+1);
}
printf("%lld\n",A.Maxflow(ss,tt));
}
return 0;
}