题目:
http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=5300
题意:
n个点,m条边,起点s终点t,构成无向图。
为了使得两个点无法联通,删去的边的权值最小且边数最少,求出剩下的边总权值/ 删去的边数。
思路:
最小割。
边权 c = c*10000+1;
flow/10000 为删去的边权值,flow%10000 为删去的边数。
AC.
#include <iostream>
#include <cstdio>
#include <cmath>
#include <algorithm>
#include <cstring>
#include <vector>
using namespace std;
const int INF = 0x3f3f3f;
const int maxn = 200;
const int maxm = 4000;
int n, m;
struct edge {
int to, cap, rev;
edge(int t, int c, int r) {
to = t; cap = c; rev = r;
}
};
vector<edge> G[2*maxn];
bool used[2*maxn];
int sum;
void init()
{
sum = 0;
for(int i = 0; i <= n; ++i) {
G[i].clear();
}
}
void addedge(int from, int to, int cap)
{
G[from].push_back(edge(to, cap, G[to].size()));
G[to].push_back(edge(from, 0, G[from].size()-1));
}
int dfs(int v, int t, int f)
{
if(v == t) return f;
used[v] = true;
for(int i = 0; i < G[v].size(); ++i) {
edge &e = G[v][i];
if(!used[e.to] && e.cap > 0) {
int d = dfs(e.to, t, min(f, e.cap));
if(d > 0) {
e.cap -= d;
G[e.to][e.rev].cap += d;
return d;
}
}
}
return 0;
}
int max_flow(int s, int t)
{
int flow = 0;
while(1) {
memset(used, 0, sizeof(used));
int f = dfs(s, t, INF);
if(f == 0) return flow;
flow += f;
sum++;
}
return flow;
}
int main()
{
//freopen("in", "r", stdin);
int T;
scanf("%d", &T);
while(T--) {
int s, t;
scanf("%d %d %d %d", &n, &m, &s, &t);
init();
int ss = 0;
for(int i = 0; i < m; ++i) {
int u, v, w;
scanf("%d %d %d", &u, &v, &w);
ss += w;
addedge(u, v, w*10000+1);
addedge(v, u, w*10000+1);
}
int f = max_flow(s, t);
int res = ss - f/10000;
int bn = f%10000;
if(res == ss) {
printf("Inf\n");
}
else {
double ans = (double)res/bn;
printf("%.2lf\n", ans);
}
}
}