• poj3308Paratroopers(最小割)


    题目请戳这里

    题目大意:给一个n*m的矩阵,给一些点(ri,ci)表示该点在第ri行第ci列。现在要覆盖所有的点,已知覆盖第i行代价为Ri,覆盖第j列代价为Cj。总代价是累乘的,求最小总代价能覆盖所有的点。

    题目分析:最小割。增加一个超级源点和超级汇点,源点到行连边,边权为覆盖行的代价,每列到汇点建边,边权为覆盖该列的代价。对于给定的点对,ri->cj连边,边权无穷大。求一个最小割即可。因为根据割的性质,会将图分成2部分,一部分含源点,一部分含汇点,那么这个割集的边只可能为s->ri、ri->cj、cj->t中的某些边,而ri->cj权是无穷大的,所以不会选这些边,因此割集必在s->ri和cj->t中,那么割集中的边就代表选中要覆盖的行和列,因为要总代价最小,所以求出最小割就是最小总代价。

    因为总代价是累乘的,所以要化乘法为加法,取对数。

    trick:输出浮点数的时候%.f,%.lf会WA。。。

    详情请见代码:

    #include <iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int N = 105;
    const int M = 5500;
    const double inf = 100000000.0;
    const double eps = 1e-8;
    int m,n,l,num;
    struct node
    {
        double c;
        int to,next,pre;
    }arc[M];
    int head[N],sta[N],que[N],cnt[N],dis[N],rpath[N];
    void build(int s,int e,double cap)
    {
        arc[num].to = e;
        arc[num].c = cap;
        arc[num].next = head[s];
        head[s] = num ++;
        arc[num - 1].pre = num;
        arc[num].pre = num - 1;
        arc[num].to = s;
        arc[num].c = 0.0;
        arc[num].next = head[e];
        head[e] = num ++;
    }
    void re_Bfs()
    {
        int i,front,rear;
        for(i = 0;i <= n + m + 1;i ++)
        {
            dis[i] = n + m + 2;
            cnt[i] = 0;
        }
        front = rear = 0;
        dis[n + m + 1] = 0;
        cnt[0] = 1;
        que[rear ++] = n + m + 1;
        while(front != rear)
        {
            int u = que[front ++];
            for(i = head[u];i != -1;i = arc[i].next)
            {
                if(arc[arc[i].pre].c < eps || dis[arc[i].to] < n + m + 2)
                    continue;
                dis[arc[i].to] = dis[u] + 1;
                cnt[dis[arc[i].to]] ++;
                que[rear ++] = arc[i].to;
            }
        }
    }
    void ISAP()
    {
        re_Bfs();
        int i,u;
        double maxflow = 0.0;
        for(i = 0;i <= n + m + 1;i ++)
            sta[i] = head[i];
        u = 0;
        while(dis[0] < n + m + 2)
        {
            if(u == n + m + 1)
            {
                double curflow = inf;
                for(i = 0;i != m + n + 1;i = arc[sta[i]].to)
                    curflow = min(curflow,arc[sta[i]].c);
                for(i = 0;i != m + n + 1;i = arc[sta[i]].to)
                {
                    arc[sta[i]].c = arc[sta[i]].c - curflow;
                    arc[arc[sta[i]].pre].c = arc[arc[sta[i]].pre].c + curflow;
                }
                maxflow = maxflow + curflow;
                u = 0;
            }
            for(i = sta[u];i != -1;i = arc[i].next)
                if(arc[i].c > eps && dis[arc[i].to] + 1 == dis[u])
                    break;
            if(i != -1)
            {
                sta[u] = i;
                rpath[arc[i].to] = arc[i].pre;
                u = arc[i].to;
            }
            else
            {
                if((-- cnt[dis[u]]) == 0)
                    break;
                sta[u] = head[u];
                int Min = m + n + 2;
                for(i = sta[u];i != -1;i = arc[i].next)
                    if(arc[i].c > eps)
                        Min = min(Min,dis[arc[i].to]);
                dis[u] = Min + 1;
                cnt[dis[u]] ++;
                if(u != 0)
                    u = arc[rpath[u]].to;
            }
        }
        printf("%.4lf
    ",pow(10.0,maxflow));
    }
    int main()
    {
        int t,i;
        int a,b;
        double x;
        scanf("%d",&t);
        while(t --)
        {
            memset(head,-1,sizeof(head));
            scanf("%d%d%d",&n,&m,&l);
            for(i = 1;i <= n;i ++)
            {
                scanf("%lf",&x);
                build(0,i,log10(x));
            }
            for(i = 1;i <= m;i ++)
            {
                scanf("%lf",&x);
                build(n + i,m + n + 1,log10(x));
            }
            while(l --)
            {
                scanf("%d%d",&a,&b);
                build(a,n + b,inf);
            }
            ISAP();
        }
        return 0;
    }
    //568K	16MS


  • 相关阅读:
    ThreadPoolExecutor线程池参数设置技巧
    函数式接口
    Mac下进入MySQL命令行
    Java8 特性
    Java8 :: 用法 (JDK8 双冒号用法)
    事务传播
    新版IDEA配置tomcat教程(2018)
    Java8 Map的compute()方法
    Spring 普通类与工具类调用service层
    简单工厂(三)——JDK源码中的简单工厂
  • 原文地址:https://www.cnblogs.com/james1207/p/3318002.html
Copyright © 2020-2023  润新知