zoj 3792 Romantic Value(最小割下边数最小)

http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5300


大致题意:给出一个无向图,以及起点与终点。要删除一些边使得起点与终点不连通,在删掉边的权值之和最小的情况下要求删除的边数尽量少。求出一个比值:剩余边数权值和/删除的边数。


思路:删除边的权值之和最小显然是求最小割即最大流。但同时要求删除边数最少,解决方法是把边数也加到权值上去,一起求最大流,因为边数最多是1000,即每条边的边权置为 w*10000+1,1代表这一条边。然后求最小割,同时也把最小边数求了出来。若求得的最小割是ans,那么删除的边数为ans%10000,最小割是ans/10000。


#include <stdio.h>
#include <iostream>
#include <map>
#include <stack>
#include <vector>
#include <math.h>
#include <string.h>
#include <queue>
#include <string>
#include <stdlib.h>
#include <algorithm>
#define LL long long
#define _LL __int64
#define eps 1e-8
#define PI acos(-1.0)
using namespace std;

const int INF = 0x3f3f3f3f;
const int maxn = 55;
const int maxm = 1010;

struct node
{
	int v,w,next,re;
}edge[4*maxm];

int n,m,s,t;
int cnt,head[maxn];
int dis[maxn],vis[maxn];
queue <int> que;

void init()
{
	cnt = 0;
	memset(head,-1,sizeof(head));
}

void add(int u, int v, int w)
{
	edge[cnt] = ((struct node){v,w,head[u],cnt+1});
	head[u] = cnt++;

	edge[cnt] = ((struct node){u,0,head[v],cnt-1});
	head[v] = cnt++;
}

bool bfs()
{
	memset(vis,0,sizeof(vis));
	memset(dis,0,sizeof(dis));
	while(!que.empty()) que.pop();

	dis[s] = 0;
	vis[s] = 1;
	que.push(s);

	while(!que.empty())
	{
		int u = que.front();
		que.pop();
		for(int i = head[u]; i != -1; i = edge[i].next)
		{
			int v = edge[i].v;
			if(!vis[v] && edge[i].w)
			{
				vis[v] = 1;
				que.push(v);
				dis[v] = dis[u] + 1;
			}
		}
	}
	if(dis[t] == 0)
		return false;
	return true;
}

int dfs(int u, int delta)
{
	if(u == t)
		return delta;
	int ret = 0,tmp;

	for(int i = head[u]; i != -1; i = edge[i].next)
	{
		int v = edge[i].v;
		if(edge[i].w && dis[v] == dis[u] + 1 && (tmp = dfs(v,min(delta,edge[i].w))))
		{
			edge[i].w -= tmp;
			edge[edge[i].re].w += tmp;
			return tmp;
		}
	}
	if(!ret)
		dis[u] = -1;
	return ret;
}

int Dinic()
{
	int ans = 0,res;
	while(bfs())
	{
		while(res = dfs(s,INF))
			ans += res;
	}
	return ans;
}

int main()
{
	int test;
	int u,v,w;
	int sum;

	scanf("%d",&test);
	while(test--)
	{
		scanf("%d %d %d %d",&n,&m,&s,&t);
		init();
		sum = 0;
		for(int i = 1; i <= m; i++)
		{
			scanf("%d %d %d",&u,&v,&w);
			add(u,v,w*10000+1);
			add(v,u,w*10000+1);
			sum += w;
		}

		int ans = Dinic();
		if(ans == 0)
		{
			printf("Inf\n");
			continue;
		}

		int a = sum - ans/10000;
		int b = ans%10000;
		printf("%.2lf\n",(double)a/b);
	}
	return 0;
}






你可能感兴趣的:(图论,最小割)