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;    
}