瞎YY一下发现显然在方案确定的情况下把所有费用分配在流量最大的边上最优,于是只要二分最大流量每次容量和二分的值取min跑最大流看是否和原最大流相等即可。
流量可以是小数!!坑死我了,我还以为保留小数是逗你玩呢
#include<iostream>
#include<cstdlib>
#include<cstdio>
#include<cstring>
#include<ctime>
#include<cmath>
#include<algorithm>
#include<iomanip>
#include<queue>
#include<map>
#include<bitset>
#include<stack>
#include<vector>
#include<set>
using namespace std;
#define MAXN 110
#define MAXM 2010
#define INF 1000000000
#define MOD 1000000007
#define ll long long
#define eps 1e-8
struct vec{
int to;
int fro;
double v;
};
vec mp[MAXM];
int tai[MAXN],cnt=1;
int d[MAXN];
int q[MAXN],hd,tl;
int s,t;
int v1[MAXM],v2[MAXM],v[MAXM];
int n,m,p;
double mf;
inline void be(int x,int y,double z){
mp[++cnt].to=y;
mp[cnt].fro=tai[x];
tai[x]=cnt;
mp[cnt].v=z;
}
inline void bse(int x,int y,double z){
be(x,y,z);
be(y,x,0);
}
bool bfs(){
int i,x,y;
memset(d,0,sizeof(d));
d[1]=1;
hd=tl=0;
q[tl++]=1;
while(hd!=tl){
x=q[hd++];
for(i=tai[x];i;i=mp[i].fro){
y=mp[i].to;
if(!d[y]&&mp[i].v>0){
d[y]=d[x]+1;
q[tl++]=y;
}
}
}
return d[t];
}
double dfs(int x,double mx){
if(x==t){
return mx;
}
int i,y;
double tmp,re=0;
for(i=tai[x];i;i=mp[i].fro){
y=mp[i].to;
if(d[y]==d[x]+1&&mp[i].v>0){
tmp=dfs(y,min(mx,mp[i].v));
re+=tmp;
mx-=tmp;
mp[i].v-=tmp;
mp[i^1].v+=tmp;
if(mx<eps){
return re;
}
}
}
if(re<eps){
d[x]=0;
}
return re;
}
bool OK(double x){
int i;
cnt=1;
memset(tai,0,sizeof(tai));
for(i=1;i<=m;i++){
bse(v1[i],v2[i],min(x,1.0*v[i]));
}
double re=0;
while(bfs()){
re+=dfs(s,INF);
}
return fabs(re-mf)<eps;
}
int main(){
int i;
scanf("%d%d%d",&n,&m,&p);
s=1;
t=n;
for(i=1;i<=m;i++){
scanf("%d%d%d",&v1[i],&v2[i],&v[i]);
bse(v1[i],v2[i],v[i]);
}
while(bfs()){
// cout<<dfs(s,INF)<<'#'<<endl;
mf+=dfs(s,INF);
}
double l=0,r=50000;
double ans;
while(fabs(l-r)>eps){
double mid=(l+r)/2;
if(OK(mid)){
ans=mid;
r=mid;
}else{
l=mid;
}
}
printf("%d\n%.4lf\n",int(mf),1.0*p*ans);
return 0;
}
/*
6 6 1
1 2 2
2 3 2
3 6 2
1 4 2
4 5 4
5 6 2
*/