uva10594 (无向图的最小费用流)

题目大意:
给出每条边可以承载的最大容量,然后给出连接的边和他们的费用。
求是否可以以最小的费用将指定重量的东西载到对面。

思路:
最小费用最大流。
因为是无向图的证明可以来回走,
只要添加从u到v的边再添加从v到u的边就可以了。
有向图中添加反向边的原因是可以反悔走过的路。

代码:

#include <iostream>
using namespace std;
#include <cstring>
#include <stdio.h>
#include <queue>

const int INF = 0x3f3f3f3f;
const int MAX = 110;
int n,m;
int f;
long long c;
int D,K;
int p[MAX];
int edgenum;
int first[MAX];
int vis[MAX];
long long  dis[MAX];//记住要long long
struct node {
    int u,v;
    long long cost;
    int flow;
    int ne;
    int cap;
}e[50000];

struct node1{
    int u,v,w;
}E[5050];
void addedge(int u,int v,int w,int cap) {
    e[edgenum].u = u;
    e[edgenum].v = v;
    e[edgenum].cost = w;
    e[edgenum].flow = 0;
    e[edgenum].cap = cap;
    e[edgenum].ne = first[u];
    first[u] = edgenum++;
    e[edgenum].u = v;
    e[edgenum].v = u;
    e[edgenum].cost = -w;
    e[edgenum].flow = 0;
    e[edgenum].cap = 0;
    e[edgenum].ne = first[v];
    first[v] = edgenum++;
}
void EK() {
    queue<int> q;
    c = f = 0;
    while(1) {
        for(int i = 0; i <= n; i++)
            dis[i] = INF;
        dis[0] = 0;
        memset(p,-1,sizeof(p));
        memset(vis,0,sizeof(vis));
        q.push(0);
        while(!q.empty()) {
            int u = q.front();
            q.pop();
            vis[u] = 0;
            for(int i = first[u];i != -1; i = e[i].ne) {
                int v = e[i].v;
                if(e[i].cap > e[i].flow &&dis[v] > dis[u] + e[i].cost) {
                    dis[v] = dis[u] + e[i].cost;
                    p[v] = i;
                    if(!vis[v]) {
                        vis[v] = 1;
                        q.push(v);
                    }
                }
            }
        }
        if(dis[n] == INF)
            break;
        int a = INF;
        for(int i = p[n];i != -1; i = p[e[i^1].v])
            a = min(a,e[i].cap - e[i].flow);
        for(int i = p[n]; i != -1; i = p[e[i^1].v]) {
            e[i].flow += a;
            e[i^1].flow -= a;
        }
        c += dis[n] * a;
        f += a;
    }

}
int main() {

    while(scanf("%d %d",&n,&m) != EOF) {
        for(int i = 1; i <= m; i++) 
            scanf("%d %d %d",&E[i].u,&E[i].v,&E[i].w);
        scanf("%d %d",&D,&K);
        memset(first,-1,sizeof(first));
        edgenum = 0;
        addedge(0,1,0,D);
        //memset(first,-1,sizeof(first));
        for(int i = 1; i <= m; i++) {
            addedge(E[i].u,E[i].v,E[i].w,K);
            addedge(E[i].v,E[i].u,E[i].w,K);
        }
        EK();
        if(f == D)
            printf("%lld\n",c);
        else
            printf("Impossible.\n");
    }

    return 0;
}

你可能感兴趣的:(uva10594 (无向图的最小费用流))