题目链接:点击打开链接
解题思路:
第一种:先跑一遍最大流,然后把正向满流的边容量+1,不满流的容量变成inf,再跑一遍最大流。
说明:割边一定满流,满流不一定是割边。我们将满流的边容量+1,那么在最少割边位置不变的情况下,求出的最大流的值就是割边数*1==割边数。将不满流的容量变为inf这样确保他们不会变成满流也不会影响到满流边变成不满流,也就是割边还是不会被他影响。将满流边容量+1,首先我们知道不是割边但满流,一定是多条满流汇入一条割边所形成的,那么他们都+1只会造成割边还是割边,满流边可能不满流而已。所以确保了割边不变。
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int mx = 1e3 + 10;
int n,m,S,T,tot,head[mx],cur[mx];
struct node
{
int y,v;
int nxt;
}edge[mx<<1];
void AddEdge(int x,int y,int v)
{
edge[tot].y = y;
edge[tot].v = v;
edge[tot].nxt = head[x];
head[x] = tot++;
}
int dep[mx];
bool bfs()
{
memset(dep,0,sizeof(dep));
queue<int> que;
que.push(S);
dep[S] = 1;
while(!que.empty())
{
int no = que.front();
que.pop();
for(int i=head[no];~i;i=edge[i].nxt)
{
int y = edge[i].y;
if(edge[i].v&&!dep[y]){
dep[y] = dep[no] + 1;
que.push(y);
}
}
}
return dep[T];
}
int dfs(int x,int flow)
{
if(x==T || !flow) return flow;
int used = 0;
for(int& i=cur[x];~i;i=edge[i].nxt)
{
int y = edge[i].y;
if(dep[x]+1==dep[y]){
int w = dfs(y,min(flow-used,edge[i].v));
edge[i].v -= w;
edge[i^1].v += w;
used += w;
if(used==flow) return flow;
}
}
//if(!used) dep[x] = 0;
return used;
}
int maxflow()
{
int ans = 0;
while(bfs()){
copy(head,head+mx,cur);
ans += dfs(S,inf);
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
scanf("%d%d",&S,&T);
int a,b,c;
tot = 0;
memset(head,-1,sizeof(head));
for(int i=1;i<=m;i++){
scanf("%d%d%d",&a,&b,&c);
AddEdge(a,b,c);
AddEdge(b,a,0);
}
int ans = maxflow();
for(int i=0;i<tot;i+=2){
if(!edge[i].v) edge[i].v = 1;
else edge[i].v = inf;
}
printf("%d\n",maxflow());
}
return 0;
}
第二种:将原来的边值变成边值*((m+1)或者是一个大数)+1,然后最后求出来的最大流%((m+1)或者是一个大数)就可以了。
说明:原图的最小割为为x1、x2、x3...,即∑x,处理后的最小割为∑x*(M+1)+B,其中B为原图最小割边的数量,如果能有边数更少的情况,处理后最小割也会相应的减少,所以处理后得到的B即为最少边数。
#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;
typedef long long ll;
const int mx = 1e3 + 10;
int n,m,S,T,tot,head[mx],cur[mx];
struct node
{
int y,v;
int nxt;
}edge[mx<<1];
void AddEdge(int x,int y,int v)
{
edge[tot].y = y;
edge[tot].v = v;
edge[tot].nxt = head[x];
head[x] = tot++;
}
int dep[mx];
bool bfs()
{
memset(dep,0,sizeof(dep));
queue<int> que;
que.push(S);
dep[S] = 1;
while(!que.empty())
{
int no = que.front();
que.pop();
for(int i=head[no];~i;i=edge[i].nxt)
{
int y = edge[i].y;
if(edge[i].v&&!dep[y]){
dep[y] = dep[no] + 1;
que.push(y);
}
}
}
return dep[T];
}
int dfs(int x,int flow)
{
if(x==T || !flow) return flow;
int used = 0;
for(int& i=cur[x];~i;i=edge[i].nxt)
{
int y = edge[i].y;
if(dep[x]+1==dep[y]){
int w = dfs(y,min(flow-used,edge[i].v));
edge[i].v -= w;
edge[i^1].v += w;
used += w;
if(used==flow) return flow;
}
}
//if(!used) dep[x] = 0;
return used;
}
int maxflow()
{
int ans = 0;
while(bfs()){
copy(head,head+mx,cur);
ans += dfs(S,inf);
}
return ans;
}
int main()
{
int t;
scanf("%d",&t);
while(t--){
scanf("%d%d",&n,&m);
scanf("%d%d",&S,&T);
int a,b,c;
tot = 0;
memset(head,-1,sizeof(head));
for(int i=1;i<=m;i++){
scanf("%d%d%d",&a,&b,&c);
AddEdge(a,b,c*(m+1)+1);
AddEdge(b,a,0);
}
int ans = maxflow()%(m+1);
printf("%d\n",ans);
}
return 0;
}