HDU-5988 Coding Contest

来源:互联网 发布:怎么进入尼尔森数据网 编辑:程序博客网 时间:2024/06/05 17:03

这个题真的又长见识了。题目要求破坏最小的概率,我们可以求出不被破坏的最大概率,因为要乘积最大,所以我们可以取对数变成加。然后跑最大费用最大流就可以了。
然后一直T到死。这里需要加一个eps剪枝,在spfa中,不然就T到死。

#include <cstdio>#include <queue>#include <cmath>using namespace std;const int MAXN = 100+5;const double inf = 1e300;const double eps = 1e-6;int n,m;int s,e;int cnt,head[MAXN];struct node{    int u,v,f,next;    double w;} edge[30000];void init(){    cnt = 0;    for(int i = 0; i <= e; ++i)head[i] = -1;}void add(int u,int v,double w,int f){    edge[cnt].u = u;    edge[cnt].v = v;    edge[cnt].w = w;    edge[cnt].f = f;    edge[cnt].next = head[u];    head[u] = cnt++;    edge[cnt].u = v;    edge[cnt].v = u;    edge[cnt].w = -w;    edge[cnt].f = 0;    edge[cnt].next = head[v];    head[v] = cnt++;}bool vis[MAXN];double dis[MAXN];int pre[MAXN];bool spfa(){    for(int i = 0; i <= e; ++i)    {        dis[i] = inf;        pre[i] = -1;    }    queue<int>q;    q.push(s);    dis[s] = 0;    while(!q.empty())    {        int u = q.front();        q.pop();        vis[u] = 0;        for(int i = head[u]; i != -1; i = edge[i].next)        {            int v = edge[i].v;            double w = edge[i].w;            int f = edge[i].f;            if(f > 0 && dis[v] - dis[u] - w > eps)            {                dis[v] = dis[u] + w;                pre[v] = i;                if(!vis[v])                {                    vis[v] = 1;                    q.push(v);                }            }        }    }    if(pre[e] == -1)return 0;    return 1;}double get_mincost(){    double min_cost = 0;    while(spfa())    {        int p = pre[e];        int flow = 200000;        while(p != -1)        {            flow = flow < edge[p].f?flow : edge[p].f;            p = pre[edge[p].u];        }        min_cost += flow*dis[e];        if(pow(2,-min_cost) <= 0.005)break;        p = pre[e];        while(p != -1)        {            edge[p].f -= flow;            edge[p^1].f += flow;            p = pre[edge[p].u];        }    }    return min_cost;}int main(){    int t;    scanf("%d",&t);    while(t--)    {        scanf("%d%d",&n,&m);        s = 0,e = n+1;        init();        int a,b;        for(int i = 1; i <= n; ++i)        {            scanf("%d%d",&a,&b);            add(s,i,0,a-b);            add(i,e,0,b-a);        }        int u,v,f;        double w;        while(m--)        {            scanf("%d%d%d%lf",&u,&v,&f,&w);            add(u,v,0,1);            add(u,v,-log2(1.0-w),f-1);        }        printf("%.2f\n",1-pow(2,-get_mincost()));    }    return 0;}
原创粉丝点击