题目链接:HDU 6214
题目大意
有向图, 求能让两个点完全分割开来所需要割去的最少边
思路
两种方法, 一种是先一遍最大流, 然后满载的边容量变成1, 其他变成INF, 再一遍最大流, 得到的就是最少需要割去的边数
另一种是每一个边的权值*m+1, (m为一个比较大的数), 然后求最小割, 得到的值对m取余就是答案
第一种算法有点问题
如图
代码
两遍最大流
312MS 1960K 2597 B G++
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
const ll INF = 0X3F3F3F3F3F3F3F3F;
const int MAXV = 222;
struct edge
{
int to, rev;
ll cap, flow;
edge(int To, ll Cap, int Rev, ll Flow)
:to(To), cap(Cap), rev(Rev), flow(Flow){}
};
vector<edge> G[MAXV];
int iter[MAXV];
int level[MAXV];
int S, T;
void add_edge(int from, int to, ll cap)
{
G[from].push_back(edge(to, cap, int(G[to].size()), 0));
G[to].push_back(edge(from, 0, 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;
}
ll dfs(int v, ll 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])
{
ll 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;
}
ll max_flow()
{
ll flow = 0;
while(bfs())
{
memset(iter, 0, sizeof(iter));
ll f;
while((f=dfs(S, INF))) flow += f;
}
return flow;
}
int main()
{
int TT;
for(scanf("%d", &TT); TT; --TT)
{
int n, m;
scanf("%d%d", &n, &m);
for(int i=1; i<=n; ++i) G[i].clear();
scanf("%d%d", &S, &T);
for(int i=0; i<m; ++i)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add_edge(u, v, w);
}
max_flow();
for(int i=1; i<=n; ++i)
{
for(auto &ite : G[i])
{
if(ite.cap != 0)
{
if(ite.flow == ite.cap)
{
ite.cap = 1;
ite.flow = 0;
// G[ite.to][ite.rev].flow = 0;
}
else
{
ite.cap = 1e9;
ite.flow = 0;
// G[ite.to][ite.rev].flow = 0;
}
}
}
}
cout << max_flow() << endl;
}
return 0;
}
权值乘以一个大数再加一
171MS 1956K 2319 B G++
#include <iostream>
#include <algorithm>
#include <cstring>
#include <cstdio>
#include <vector>
#include <queue>
using namespace std;
typedef long long ll;
const ll INF = 0X3F3F3F3F3F3F3F3F;
const int MAXV = 222;
struct edge
{
int to, rev;
ll cap, flow;
edge(int To, ll Cap, int Rev, ll Flow)
:to(To), cap(Cap), rev(Rev), flow(Flow){}
};
vector<edge> G[MAXV];
int iter[MAXV];
int level[MAXV];
int S, T;
void add_edge(int from, int to, ll cap)
{
G[from].push_back(edge(to, cap, int(G[to].size()), 0));
G[to].push_back(edge(from, 0, 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;
}
ll dfs(int v, ll 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])
{
ll 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;
}
ll max_flow()
{
ll flow = 0;
while(bfs())
{
memset(iter, 0, sizeof(iter));
ll f;
while((f=dfs(S, INF))) flow += f;
}
return flow;
}
int main()
{
int TT;
for(scanf("%d", &TT); TT; --TT)
{
int n, m;
scanf("%d%d", &n, &m);
for(int i=1; i<=n; ++i) G[i].clear();
scanf("%d%d", &S, &T);
for(int i=0; i<m; ++i)
{
int u, v, w;
scanf("%d%d%d", &u, &v, &w);
add_edge(u, v, w*10000+1);
}
cout << max_flow()%10000 << endl;
}
return 0;
}