zoukankan      html  css  js  c++  java
  • HIT 2543 Stone IV

    HIT_2543

        实际每条边一共有两种费用,一种是为0,另一种是c2,而且为0的费用对应的容量是c1,为c2的费用对应的容量是INF。既然一条边有着两条边的属性,不如索性拆成两条边算了,一条容量c1费用为0的边,和一条容量为INF费用为c2的边。

        由于c2>=0,我们在做费用流的时候会优先选择容量c1费用为0的边,这样就保证了结果是正确的。

    #include<stdio.h>
    #include<string.h>
    #include<algorithm>
    #define MAXD 1010
    #define MAXM 80010
    #define INF 0x3f3f3f3f
    int N, M, C, P, first[MAXD], e, next[MAXM], u[MAXM], v[MAXM], flow[MAXM], cost[MAXM];
    int S, T, q[MAXD], pre[MAXD], dis[MAXD], inq[MAXD];
    const int Q = 1000;
    void add(int x, int y, int f, int c)
    {
        u[e] = x, v[e] = y, flow[e] = f, cost[e] = c;
        next[e] = first[x], first[x] = e ++;    
    }
    void init()
    {
        int i, x, y, c1, c2;
        scanf("%d%d%d%d", &N, &M, &C, &P);
        S = N, T = 1;
        memset(first, -1, sizeof(first[0]) * (N + 1));
        e = 0;
        add(S, 0, INF, P), add(0, S, 0, -P);
        for(i = 0; i < M; i ++)
        {
            scanf("%d%d%d%d", &x, &y, &c1, &c2);
            add(x, y, c1, 0), add(y, x, 0, 0), add(y, x, c1, 0), add(x, y, 0, 0);
            add(x, y, INF, c2), add(y, x, 0, -c2), add(y, x, INF, c2), add(x, y, 0, -c2);
        }
    }
    int bfs()
    {
        int i, j, x, front, rear;
        front = rear = 0;
        memset(dis, 0x3f, sizeof(dis[0]) * (N + 1));
        memset(inq, 0, sizeof(inq[0]) * (N + 1));
        dis[S] = 0, pre[S] = -1, q[rear ++] = S;
        while(front != rear)
        {
            x = q[front ++], inq[x] = 0;
            front > Q ? front = 0 : 0;
            for(i = first[x]; i != -1; i = next[i])
                if(flow[i] && dis[x] + cost[i] < dis[v[i]])
                {
                    dis[v[i]] = dis[x] + cost[i], pre[v[i]] = i;
                    if(!inq[v[i]])
                    {
                        q[rear ++] = v[i], inq[v[i]] = 1;
                        rear > Q ? rear = 0 : 0;    
                    }
                }    
        }
        return dis[T] != INF;    
    }
    void solve()
    {
        int i, a, f = 0, c = C;
        while(bfs())
        {
            
            for(i = pre[T], a = INF; i != -1; i = pre[u[i]])    
                a = std::min(a, flow[i]);
            if((long long)a * dis[T] > c)
            {
                f += c / dis[T];
                break;
            }
            for(i = pre[T]; i != -1; i = pre[u[i]])
                flow[i] -= a, flow[i ^ 1] += a;
            f += a, c -= a * dis[T];
        }
        printf("%d\n", f);
    }
    int main()
    {
        int t;
        scanf("%d", &t);
        while(t --)
        {
            init();
            solve();    
        }
        return 0;    
    }
  • 相关阅读:
    js代码细嚼慢咽
    HTML知识点记录

    css知识点
    算法第五章作业
    算法第五章上机实践报告
    算法第四章上机实践报告
    算法第四章作业
    算法第三章上机实践报告
    算法第三章作业
  • 原文地址:https://www.cnblogs.com/staginner/p/2639767.html
Copyright © 2011-2022 走看看