CF653D 题目链接
Code:
#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#include<set>
#include<map>
#include<cmath>
#include<queue>
#include<sstream>
#include<string>
#include<bitset>
#include<utility>
#include<numeric>
#include<assert.h>
using namespace std;
#define rep(i,a,n) for (int i=a;i<n;i++)
#define repn(i,a,n) for (int i=a;i<=n;i++)
const int MAXN = 2 * 55;//点数的最大值
const int MAXM = 2 * 510;//边数的最大值
const int INF=0x3f3f3f3f;
const double eps = 1e-12;
int n, m, x;
int A[MAXM], B[MAXM], C[MAXM];
const int inf=0x20202020;
typedef int flowt;
namespace flow {
const int M = 1010, N = 55;
int y[M],nxt[M],gap[N],fst[N],c[N],pre[N],q[N],dis[N];
flowt f[M];
int S,T,tot,Tn;
void init(int s,int t,int tn) {
tot=1; assert(tn<N);
rep(i,0,tn) fst[i]=0;
S=s;T=t;Tn=tn;
}
void addedge(int u,int v,flowt c1,flowt c2=0) {
tot++;y[tot]=v;f[tot]=c1;nxt[tot]=fst[u];fst[u]=tot;
tot++;y[tot]=u;f[tot]=c2;nxt[tot]=fst[v];fst[v]=tot;
}
flowt sap() {
int u=S,t=1;flowt flow=0;
rep(i,0,Tn) c[i]=fst[i],dis[i]=Tn,gap[i]=0;
q[0]=T;dis[T]=0;pre[S]=0;
rep(i,0,t) {
int u=q[i];
for (int j=fst[u];j;j=nxt[j]) if (dis[y[j]]>dis[u]+1&&f[j^1])
q[t++]=y[j],dis[y[j]]=dis[u]+1;
}
rep(i,0,Tn) gap[dis[i]]++;
while (dis[S]<=Tn) {
while (c[u]&&(!f[c[u]]||dis[y[c[u]]]+1!=dis[u])) c[u]=nxt[c[u]];
if (c[u]) {
pre[y[c[u]]]=c[u]^1;
u=y[c[u]];
if (u==T) {
flowt minf=inf;
for (int p=pre[T];p;p=pre[y[p]]) minf=min(minf,f[p^1]);
for (int p=pre[T];p;p=pre[y[p]]) f[p^1]-=minf,f[p]+=minf;
flow+=minf;u=S;
}
} else {
if (!(--gap[dis[u]])) break;
int mind=Tn;
c[u]=fst[u];
for (int j=fst[u];j;j=nxt[j]) if (f[j]&&dis[y[j]]<mind)
mind=dis[y[j]],c[u]=j;
dis[u]=mind+1;
gap[dis[u]]++;
if (u!=S) u=y[pre[u]];
}
}
return flow;
}
};
int getAns(double wi)
{
int u,v,z;
double tmp;
flow::init(1, n, n + 1);
for(int i = 0; i < m; i++)
{
u = A[i], v = B[i];
tmp = C[i] / wi;
if(tmp > x) tmp = x;
z = (int)tmp;
if(z > 0)
{
flow::addedge(u,v,z);
}
}
int ans=flow::sap();
return ans;
}
int main()//多源多汇点,在前面加个源点,后面加个汇点,转成单源单汇点
{
#ifndef ONLINE_JUDGE
freopen("D.in", "r", stdin);
// freopen("test.out", "w", stdout);
#endif
while(scanf("%d%d%d",&n,&m,&x)!=EOF)
{
double L = 1.0 / x, R = 0.0;
for(int i = 0; i < m; i++)
{
scanf("%d %d %d", &A[i], &B[i], &C[i]);
R = max(R, 0.0 + C[i]);
}
double ans = 0.0;
rep(lcnt, 0, 60)
{
double mid = (R + L) * 0.5;
int num = getAns(mid);
if(num >= x) L = mid;
else R = mid;
// printf("mid = %.2lf num = %d\n", mid, num);
}
ans = R * x;
printf("%.8lf\n", ans);
}
return 0;
}