Problem Description
给你n个地点,m条边。接下来n个地点每个地点有num个人,food个人的食物。接下来m行,u地点到v地点,能经过的人数num,经过一个人发生故障的概率w, 第一个人通过的时候,发生故障概率为0。让你尽可能多的人吃到午餐,发生故障的最小概率
思路:
发生故障的概率 = 1 - 不发生故障的概率。每条边不发生故障的概率1-w。发生故障概率为0所以不发生故障概率为1。我们要求发生故障概率最小,那就是求不发生故障的概率最大。所以变成了求最大费
还有一点不能理解,反向费用的边为何是-w不是1/w。
#include<bits/stdc++.h>
using namespace std;
#define nn 105
#define inf 0x3f3f3f3f
struct node
{
int u, to, c, next;
double w;
};
node Map[500000];
int head[3*nn], cnt, vis[3*nn], pre[3*nn], flow[3*nn];
double dist[3*nn];
void add(int u, int v, int c, double w)
{
Map[cnt].u = u;
Map[cnt].to = v;
Map[cnt].c = c;
Map[cnt].w = w;
Map[cnt].next = head[u];
head[u] = cnt++;
Map[cnt].u = v;
Map[cnt].to = u;
Map[cnt].c = 0;
Map[cnt].w = -w;//为何是-w,不是1/w。-w AC, 1/w TLE.
Map[cnt].next = head[v];
head[v] = cnt++;
}
bool spfa(int s, int e)//在求最大费的过程,求出限制流量,不然会超时。
{
memset(dist, 0, sizeof(dist));
memset(vis, 0, sizeof(vis));
memset(flow, 0, sizeof(flow));
memset(pre, -1, sizeof(pre));
queue<int> q;
q.push(s);
flow[s] = inf;
dist[s] = 1;
while(!q.empty())
{
s = q.front(); q.pop();
vis[s] = 0;
for(int i = head[s]; ~i; i = Map[i].next)
{
int to = Map[i].to, c = Map[i].c;
double w = Map[i].w;
if(c && dist[to] < dist[s] * w)
{
pre[to] = i;//记录路径
dist[to] = dist[s] * w;
flow[to] = min(flow[s], c);//求限制流量
if(!vis[to])
{
vis[to] = 1;
q.push(to);
}
}
}
}
if(!dist[e]) return 0;
else return 1;
}
double get_mincost(int s, int e)
{
double ans = 1;
while(spfa(s, e))
{
int p = pre[e];
while(p != -1)
{
for(int i = 0; i < flow[e]; i++)
{
ans *= Map[p].w;
}
Map[p].c -= flow[e];
Map[p^1].c += flow[e];
p = pre[Map[p].u];
}
}
return 1-ans;
}
int main()
{
int T, u, v, num, n, m, food, i;
double w;
scanf("%d", &T);
while(T--)
{
scanf("%d %d", &n, &m);
cnt = 0;
memset(head, -1, sizeof(head));
//建边:
for(i = 1; i <= n; i++)
{
scanf("%d %d", &num, &food);
add(0, i, num, 1);
add(i+n, 2*n+1, food, 1);
add(i, i+n, inf, 1);
}
while(m--)
{
scanf("%d %d %d %lf", &u, &v, &num, &w);
if(num) {
add(u, v, 1, 1);
num--;
}
if(num) add(u, v, num, 1 - w);
}
printf("%.2f\n", get_mincost(0, 2*n+1));
}
return 0;
}