G - Coding Contest
HDU - 5988
A coding contest will be held in this university, in a huge playground. The whole playground would be divided into N blocks, and there would be M directed paths linking these blocks. The i-th path goes from the
ui
-th block to the
vi
-th block. Your task is to solve the lunch issue. According to the arrangement, there are
si
competitors in the i-th block. Limited to the size of table,
bi
bags of lunch including breads, sausages and milk would be put in the i-th block. As a result, some competitors need to move to another block to access lunch. However, the playground is temporary, as a result there would be so many wires on the path.
For the i-th path, the wires have been stabilized at first and the first competitor who walker through it would not break the wires. Since then, however, when a person go through the i - th path, there is a chance of pi to touch
the wires and affect the whole networks. Moreover, to protect these wires, no more than ci competitors are allowed to walk through the i-th path.
Now you need to find a way for all competitors to get their lunch, and minimize the possibility of network crashing.
For the i-th path, the wires have been stabilized at first and the first competitor who walker through it would not break the wires. Since then, however, when a person go through the i - th path, there is a chance of pi to touch
the wires and affect the whole networks. Moreover, to protect these wires, no more than ci competitors are allowed to walk through the i-th path.
Now you need to find a way for all competitors to get their lunch, and minimize the possibility of network crashing.
For each test case, the first line consists of two integers N (N ≤ 100) and M (M ≤ 5000). Each of the next N lines contains two integers si and bi ( si , bi ≤ 200).
Each of the next M lines contains three integers ui , vi and ci(ci ≤ 100) and a float-point number pi (0 < pi < 1).
It is guaranteed that there is at least one way to let every competitor has lunch.
1 4 4 2 0 0 3 3 0 0 3 1 2 5 0.5 3 2 5 0.5 1 4 5 0.5 3 4 5 0.5
0.50
此题一眼网络流,不过不同的是,其是求乘积最大.
由于其是求最大值,且最大值不为0,可以求其 倒数最小
这样就变成了最小费用最大流
把加减的成分变为 乘除 负号用倒数代替
就OK了
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int MAXM=100000;
const int INF=1e9;
const double eps = 1e-8;
struct Edge
{
int to,next,cap,flow;
double cost;
Edge(int _to=0,int _next=0,int _cap=0,int _flow=0,double _cost=1.0) :
to(_to),next(_next),cap(_cap),flow(_flow),cost(_cost) {}
}edge[MAXM];
struct MinCostMaxFlow
{
int head[MAXM],tot;
int cur[MAXM];
double dis[MAXM];
bool vis[MAXM];
int ss,tt,N;
int max_flow;
double min_cost;
void init()
{
tot=0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int cap,double cost)
{
// cout << cost << 1.0/cost <<endl;
edge[tot]=Edge(v,head[u],cap,0,cost);
head[u]=tot++;
edge[tot]=Edge(u,head[v],0,0,1.0/cost);
head[v]=tot++;
}
int aug(int u,int flow)
{
if(u==tt) return flow;
vis[u]=true;
for(int i=cur[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].cap>edge[i].flow&&!vis[v]&&fabs(dis[u]-dis[v]*edge[i].cost)<eps)
{
int tmp=aug(v,min(flow,edge[i].cap-edge[i].flow));
edge[i].flow+=tmp;
edge[i^1].flow-=tmp;
cur[u]=i;
if(tmp) return tmp;
}
}
return 0;
}
bool modify_label()
{
double d=1e9;
for(int u=0;u<N;u++)
if(vis[u])
for(int i=head[u];i!=-1;i=edge[i].next)
{
int v=edge[i].to;
if(edge[i].cap>edge[i].flow&&!vis[v])
{
d=min(d,dis[v]*edge[i].cost/dis[u]);
}
}
if(fabs(d-1e9)<eps) return false;
for(int i=0;i<N;i++)
if(vis[i])
{
vis[i]=false;
dis[i]*=d;
}
return true;
}
double mincostmaxflow(int start,int end,int n)
{
ss=start,tt=end,N=n;
max_flow = 0;
min_cost = 1.0;
for(int i=0;i<=n;i++) dis[i]=1.0;
while(1)
{
for(int i=0;i<n;i++) cur[i]=head[i];
while(1)
{
for(int i=0;i<n;i++) vis[i]=false;
int tmp=aug(ss,INF);
if(tmp==0) break;
max_flow+=tmp;
for(int ii=0;ii<tmp;ii++)
{
min_cost *=dis[ss];
}
}
if(!modify_label()) break;
}
return min_cost;
}
}sol;
int n,m;
int T;
int main()
{
// freopen("data.txt","r",stdin);
// ios_base::sync_with_stdio(false);
int u,v,c;
double p;
int s,b;
int ss,tt;
scanf("%d",&T);
while(T--)
{
sol.init();
scanf("%d%d",&n,&m);
ss = 0 ;
tt = n+1;
for(int i=1;i<=n;i++)
{
scanf("%d%d",&s,&b);
if(s>b)
{
sol.addedge(ss,i,s-b,1.0);
}
else if(b>s)
{
sol.addedge(i,tt,b-s,1.0);
}
}
for(int i=0;i<m;i++)
{
scanf("%d%d%d%lf",&u,&v,&c,&p);
if(c==0) continue;
sol.addedge(u,v,1,1.0);
if(c==1) continue;
sol.addedge(u,v,c-1,1.0/(1-p));
}
printf("%.2f\n",1.0-1/sol.mincostmaxflow(ss,tt,n+3));
}
return 0;
}