hdu 6214 - 最小割最少割边

题目链接:点击打开链接


解题思路:

第一种:先跑一遍最大流,然后把正向满流的边容量+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;
}

猜你喜欢

转载自blog.csdn.net/a1214034447/article/details/81006189