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;
}