题目链接: Sabotage UVA - 10480
题目大意
一张无向图, n个顶点, m条边( n≤50,m≤500 ), 每条边有一个权值, 去除若干条边, 让顶点1和顶点2之间没有路径相连, 求去除的边权值总和最小的切割方案, 输出这个方案
思路
最小割问题
求出最小割后, 在残余网络中, 与源点之间有路径的顶点属于集合S, 其他顶点属于集合T, 所有一个顶点属于集合S, 另一个顶点属于集合T的边, 就是我们要切割的边
代码
#include <bits/stdc++.h>
using namespace std;
const int INF = 0X3F3F3F3F, MAXV = 200;
struct edge
{
int to, cap, rev, flow;
edge(int To, int Cap, int Rev, int Flow)
:to(To), cap(Cap), rev(Rev), flow(Flow){}
};
vector<edge> G[MAXV];
int iter[MAXV];
int level[MAXV];
int S, T;
void init()
{
for(int i=0; i<MAXV; ++i) G[i].clear();
}
void add_edge(int from, int to, int cap)
{
G[from].push_back(edge(to, cap, int(G[to].size()), 0));
G[to].push_back(edge(from, cap, int(G[from].size()-1), 0));
}
bool bfs()
{
memset(level, -1, sizeof(level));
queue<int> que;
level[S] = 0;
que.push(S);
while(!que.empty())
{
int v = que.front(); que.pop();
for(int i=0; i<(int)G[v].size(); ++i)
{
edge & e = G[v][i];
if(level[e.to]<0 && e.cap > e.flow)
{
level[e.to] = level[v] + 1;
que.push(e.to);
}
}
}
return level[T] != -1;
}
int dfs(int v, int f)
{
if(v == T) return f;
for(int &i=iter[v]; i<(int)G[v].size(); ++i)
{
edge &e = G[v][i];
if(e.cap>e.flow && level[e.to]>level[v])
{
int d = dfs(e.to, min(f, e.cap-e.flow));
if(d)
{
e.flow += d;
G[e.to][e.rev].flow -= d;
return d;
}
}
}
return 0;
}
int max_flow()
{
int flow = 0;
while(bfs())
{
memset(iter, 0, sizeof(iter));
int f;
while((f=dfs(S, INF))) flow += f;
}
return flow;
}
int n, m, a, b, c;
int main()
{
while(scanf("%d%d", &n, &m) == 2)
{
init();
S = 1, T = 2;
for(int i=0; i<m; ++i)
{
scanf("%d%d%d", &a, &b, &c);
add_edge(a, b, c);
}
max_flow();
set<int> ss;
ss.insert(1);
queue<int> que;
que.push(1);
bool vist[MAXV];
memset(vist, 0, sizeof(vist));
vist[1]= 1;
while(!que.empty())
{
int now = que.front(); que.pop();
for(auto &ite : G[now])
{
if(ite.flow < ite.cap && !vist[ite.to])
{
que.push(ite.to);
vist[ite.to] = 1;
ss.insert(ite.to);
}
}
}
for(int i=1; i<=n; ++i)
{
if(ss.find(i) != ss.end())
{
for(auto &ite : G[i])
{
if(ss.find(ite.to) == ss.end()) printf("%d %d\n", i, ite.to);
}
}
}
cout << endl;
}
return 0;
}