uva10594(最小费用最大流)

来源:互联网 发布:java安装错误代码1603 编辑:程序博客网 时间:2024/06/04 19:58

题目的意思就就是首先给出点的个数,在给出边的个数,然后给出每条边的费用.

然后给出的两个数字,是要从点1运到点n的物品数量.

还有每条边的容量(所有边容量一样)


因为是无向图,所以我们用邻接表存,在用最小费用最大流的算法直接算出最小费用.

但如果算出来的最大流小于我们要运的数量,说明运不过去,,


ac代码:


#include<stdio.h>#include<string.h>#include<queue>#define ll long longusing namespace std;const ll INF = 1000000000000005;const int N = 105;const int M = 5005;const int K = 20100;ll cap[K];ll flow[K];ll cost[K];ll nex[K];ll first[M];ll u[K];ll v[K];int p[N];ll a[M];ll b[M];ll g[M];ll n,m, num , maxcap;ll c, f ;int e;void add(ll s , ll t ,ll c ,ll co) {u[e] = s;v[e] = t;nex[e] = first[u[e]];first[u[e]] = e;cap[e] = c;cost[e] = co;e++;u[e] = t;v[e] = s;nex[e] = first[u[e]];first[u[e]] = e;cap[e] = 0;cost[e] = -co;e++;}void ek() {queue<int> q;memset(flow , 0 ,sizeof(flow));ll d[N];c = f = 0;while(1) {int vis[N];memset(vis , 0 ,sizeof(vis));memset(p , -1 ,sizeof(p));for (int i = 0 ; i <= n ;i++) d[i] = INF;d[0] = 0;vis[0] = 1;q.push(0);while(!q.empty()) {ll u = q.front();q.pop();vis[u] = 0;for (int i = first[u] ; i != -1 ;i = nex[i]) {int k = v[i];if(cap[i] > flow[i] & d[k] > d[u] + cost[i]) {d[k] = d[u] + cost[i];p[k] = i ;if(!vis[k]) {vis[k] = 1;q.push(k);}}}}if (d[n] == INF) break;ll w = INF ;for (int i = p[n] ; i != -1 ;i = p[u[i]]) {w = w < cap[i] - flow[i] ? w : cap[i] - flow[i];}for (int i =p[n] ; i != -1 ;i = p[u[i]]) {flow[i] += w;flow[i ^ 1] -= w;}c += d[n] * w;f += w;}return ;}int main () {while(~scanf("%lld%lld",&n,&m)) {e = 0;memset(cap , 0 ,sizeof(cap));memset(first , -1 , sizeof(first));for (int i = 1 ; i <= m ; i++) {scanf("%lld%lld%lld",&a[i],&b[i],&g[i]);}scanf("%lld%lld",&num ,&maxcap);add(0 , 1, num , 0);for (int i = 0 ; i <= m ;i++) {add(a[i] , b[i] , maxcap , g[i]);add(b[i] , a[i] , maxcap , g[i]);}ek();if (f == num) printf("%lld\n",c);elseprintf("Impossible.\n");}}


0 0
原创粉丝点击