• hdu 4494 最小费用流


    思路:这题我在下午重现的时候就用的费用流做,可是各种悲催的超时,只是我一开始的那种建图方式多了一个二分查找。

    戏剧性的是,求距离的返回值写成int型了,CodeBlock编译器又没有警告,然后就WA啊WA,AC率一下就被拉低了。

    当然,对每种工人分别建图是不变的,因为每种工人互不影响。

    后来想到了一个较好的建图方式,将每个点拆成3个点,i,i+n,i+2*n。

    1号点就是仓库,也就是超级源点,3*n+1号点为超级汇点。

    由1号点想每个i建一条流量为ty[i][j],费用为1的边。表示每次增加流量,人数就增加。

    由i向i+2*n建一条流量为ty[i][j],费用为0的边。

    由i+2*n向汇点建一条流量为ty[i][j],费用为0的边。

    由1向每个i+n建一条流量为ty[i][j],费用为0的边。

    对i号点,寻找开始时间sta[k]满足b[i]+p[i]+d[i][j]的点k,然后由i+n向k+2*n建一条流量为ty[i][j],费用为0的边。

    这样,如果i号点的工人能到k号点工作,那么k号点的k+2*n到3*n+1的流量就会减少ty[i][j]。

    #include<iostream>
    #include<cstring>
    #include<cstring>
    #include<cmath>
    #include<cstdio>
    #define inf 100000000
    using namespace std;
    const int Maxn = 600;
    struct Edge{
        int v;
        int val;
        int cost;
        int next;
    }edge[Maxn*600];
    struct Point{
        double x,y;
    }p[Maxn];
    int head[Maxn],n,m,k;
    int e;
    int dis[Maxn],pre[Maxn], pos[Maxn],sta[Maxn],en[Maxn],ty[Maxn][20],flow;
    int  que[Maxn*600];
    double d[Maxn][Maxn];
    bool vis[Maxn];
    void add(int u, int v, int val, int cost)
    {
        edge[e].v = v;
        edge[e].val = val;
        edge[e].cost = cost;
        edge[e].next = head[u];
        head[u] = e++;
        edge[e].v = u;
        edge[e].val = 0;
        edge[e].cost = -cost;
        edge[e].next = head[v];
        head[v] = e++;
    }
    double DIS(Point a,Point b)
    {
        return sqrt((a.x-b.x)*(a.x-b.x)+(a.y-b.y)*(a.y-b.y));
    }
    void init()
    {
        memset(head,-1,sizeof(head));
        e=0;
    }
    bool spfa(int s, int t)
    {
        int i;
        memset(pre, -1, sizeof(pre));
        memset(vis, 0, sizeof(vis));
        int Head, tail;
        Head = tail = 0;
        for(i = 0; i < Maxn; i++)
            dis[i] = inf;
        que[tail++] = s;
        pre[s] = s;
        dis[s] = 0;
        vis[s] = 1;
        while(Head != tail)
        {
            int now = que[Head++];
            vis[now] = 0;
            for(i=head[now]; i != -1; i = edge[i].next)
            {
                int adj = edge[i].v;
                if(edge[i].val > 0 && dis[now] + edge[i].cost < dis[adj])
                {
                    dis[adj] = dis[now] + edge[i].cost;
                    pre[adj] = now;
                    pos[adj] = i;
                    if(!vis[adj])
                    {
                        vis[adj] = 1;
                        que[tail++] = adj;
                    }
                }
            }
        }
        return pre[t] != -1;
    }
    int MinCostFlow(int s, int t)
    {
        int i;
        int cost = 0;
        flow = 0;
        while(spfa(s, t))
        {
            int f = 100000000;
            for(i = t; i != s; i = pre[i])
            if (edge[pos[i]].val < f)
                f = edge[pos[i]].val;
                flow += f;
                cost += dis[t] * f;
                for(i = t; i != s; i = pre[i])
                {
                    edge[pos[i]].val -= f;
                    edge[pos[i] ^ 1].val += f;
                }
        }
        return cost;
    }
    void build(int type)
    {
        int i,j;
        init();
        for(i=2;i<=n;i++){
            add(1,i,ty[i][type],1);
            add(i,i+2*n,ty[i][type],0);
            add(1,i+n,ty[i][type],0);
            add(i+2*n,3*n+1,ty[i][type],0);
            for(j=2;j<=n;j++){
                if(sta[i]+en[i]+d[i][j]<=sta[j]){
                    add(i+n,j+2*n,ty[i][type],0);
                }
            }
        }
    }
    int solve()
    {
        int i,j,u,v;
        int ans=0;
        for(i=1;i<=m;i++){
            build(i);
            ans+=MinCostFlow(1,3*n+1);
        }
        return ans;
    }
    int main()
    {
        int i,j,u,v,c,t;
        scanf("%d",&t);
        while(t--)
        {
            init();
            scanf("%d%d",&n,&m);
            scanf("%lf%lf",&p[1].x,&p[1].y);
            for(i=2;i<=n;i++){
                scanf("%lf%lf%d%d",&p[i].x,&p[i].y,&sta[i],&en[i]);
                for(j=1;j<=m;j++){
                    scanf("%d",&ty[i][j]);
                }
            }
            for(i=1;i<=n;i++){
                for(j=i+1;j<=n;j++){
                    d[i][j]=d[j][i]=DIS(p[i],p[j]);
                }
            }
            printf("%d
    ",solve());
        }
        return 0;
    }
  • 相关阅读:
    应用图标大小
    AndroidStudio使用笔记
    shell 三剑客之 sed 命令详解
    shell 三剑客之 sed pattern 详解
    shell 文本处理三剑客之 grep 和 egrep
    Shell 编程中的常用工具
    shell 函数的高级用法
    shell 数学运算
    shell 变量的高级用法
    nginx 之 https 证书配置
  • 原文地址:https://www.cnblogs.com/wangfang20/p/3280172.html
Copyright © 2020-2023  润新知