題目
Coding Contest
Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 3503 Accepted Submission(s): 825
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.
解題思路
TTTTTTTTTTTTTTT哭了
思路概率要相乘所以轉化成log,第一次不計算,所以額外加一條不消耗的邊
關鍵是超時,超時,超時,用的kuangbin的板子
double判斷要用1e-8來提高速度
還發現pow似乎比exp快一些
能注意的就這麼多了,浪費我一晚上去改
如果還不行,抱歉,兄臺換板子吧,你的最小費用最大流板子可能真的不行
貼上我靠運氣卡過的代碼
#include <cstdio>
#include <iostream>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
const int MAXN = 10000;
const int MAXM = 100000;
const double eps = 1e-8;
const double INF = 999999999.0;
struct Edge
{
int to,next,cap,flow;
double cost;
} edge[MAXM];
int head[MAXN],tol;
int pre[MAXN];
double dis[MAXN];
bool vis[MAXN];
int N;//節點總個數,節點編號從0~N-1
void init(int n)
{
N = n;
tol = 0;
memset(head,-1,sizeof(head));
}
void addedge(int u,int v,int cap,double cost)
{
edge[tol].to = v;
edge[tol].cap = cap;
edge[tol].cost = cost;
edge[tol].flow = 0;
edge[tol].next = head[u];
head[u] = tol++;
edge[tol].to = u;
edge[tol].cap = 0;
edge[tol].cost = -cost;
edge[tol].flow = 0;
edge[tol].next = head[v];
head[v] = tol++;
}
typedef pair<double , int> P;
bool spfa(int s,int t)
{
queue<int> q;
for(int i = 0; i <= N; i++)
{
dis[i] = INF;
vis[i] = false;
pre[i] = -1;
}
dis[s] = 0.0;
vis[s] = true;
q.push(s);
while(!q.empty())
{
int u = q.front();
q.pop();
/// int u = tt.second;
vis[u] = false;
for(int i = head[u]; i != -1; i = edge[i].next)
{
int v = edge[i].to;
if(edge[i].cap > edge[i].flow &&
(dis[v] -(dis[u] + edge[i].cost)> eps))
{
dis[v] = dis[u] + edge[i].cost;
pre[v] = i;
if(!vis[v])
{
vis[v] = true;
q.push(v);
}
}
}
}
if(pre[t] == -1)return false;
else return true;
}
//返回的是最大流,cost存的是最小費用
int minCostMaxflow(int s,int t,double &cost)
{
int flow = 0;
cost = 0.0;
while(spfa(s,t))
{
int Min = INF;
for(int i = pre[t]; i != -1; i = pre[edge[i^1].to])
{
if(Min > edge[i].cap - edge[i].flow)
Min = edge[i].cap - edge[i].flow;
}
for(int i = pre[t]; i != -1; i = pre[edge[i^1].to])
{
edge[i].flow += Min;
edge[i^1].flow -= Min;
cost += edge[i].cost * (double)Min;
}
flow += Min;
}
return flow;
}
int main()
{
int T;
int nn, m;
scanf("%d", &T);
while(T--)
{
scanf("%d%d",&nn ,&m);
int A, B;
init(nn + 1);
for(int i = 1; i <= nn; i++)
{
scanf("%d%d", &A, &B);
if(A == B)
continue;
if(A > B)
{
addedge(0, i, A - B, 0.0);
continue;
}
if(A < B)
{
addedge(i, nn + 1, B - A, 0.0);
continue ;
}
}
int u, v, cap;
double cost;
for(int j = 0; j < m; j++)
{
scanf("%d%d%d%lf", &u, &v, &cap, &cost);
double w = -log10(1.0 - cost);
if(cap == 0)
continue ;
if(cap == 1)
addedge(u, v, 1, 0.0);
else if(cap - 1)
{
addedge(u, v, 1, 0.0);
addedge(u, v, cap - 1, w);
}
}
double ans = 0.0;
minCostMaxflow(0, N, ans);
ans = 1 - pow(10, -ans);
printf("%.2f\n", ans);
}
return 0 ;
}