hdu 6118度度熊的交易計劃(費用流)

度度熊的交易計劃

Time Limit: 12000/6000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1192    Accepted Submission(s): 440


ios

Problem Description
度度熊參與了喵哈哈村的商業大會,可是此次商業大會遇到了一個難題:

喵哈哈村以及周圍的村莊能夠看作是一共由n個片區,m條公路組成的地區。

因爲生產能力的區別,第i個片區可以花費a[i]元生產1個商品,可是最多生產b[i]個。

一樣的,因爲每一個片區的購買能力的區別,第i個片區也可以以c[i]的價格出售最多d[i]個物品。

因爲這些因素,度度熊以爲只有合理的調動物品,才能得到最大的利益。

據測算,每個商品運輸1千米,將會花費1元。

那麼喵哈哈村最多可以實現多少盈利呢?
 

 

Input
本題包含若干組測試數據。
每組測試數據包含:
第一行兩個整數n,m表示喵哈哈村由n個片區、m條街道。
接下來n行,每行四個整數a[i],b[i],c[i],d[i]表示的第i個地區,可以以a[i]的價格生產,最多生產b[i]個,以c[i]的價格出售,最多出售d[i]個。
接下來m行,每行三個整數,u[i],v[i],k[i],表示該條公路鏈接u[i],v[i]兩個片區,距離爲k[i]

可能存在重邊,也可能存在自環。

知足:
1<=n<=500,
1<=m<=1000,
1<=a[i],b[i],c[i],d[i],k[i]<=1000,
1<=u[i],v[i]<=n
 

 

Output
輸出最多能賺多少錢。
 

 

Sample Input
2 1 5 5 6 1 3 5 7 7 1 2 1
 

 

Sample Output
23
 
題解:建邊
1.創建超級源點S,對每一個片區i連容量爲b[i],費用爲a[i]的單向邊.
2.每一個片區對可達的片區連容量爲正無窮,費用爲距離k[i]的雙向邊.
3.每一個片區對匯點T連容量爲d[i],費用爲c[i]的雙向邊.
可是這樣跑出來的是最大流下的最小費用.咱們須要的是最小費用,因此當增廣路 >=0(即沒有比0小的增廣路能夠進行增廣了),直接退出,取反最小費用,便是能賺的最多的錢.
#include <iostream>
#include <algorithm>
#include <stdio.h>
#include <string.h>
#include <queue>
using namespace std;

const int INF = 999999999;
const int N = 600;
const int M = 200005;
struct Edge{
    int u,v,cap,cost,next;
}edge[M];
int head[N],tot,low[N],pre[N];
int total;
bool vis[N];
void addEdge(int u,int v,int cap,int cost,int &k){
    edge[k].u=u,edge[k].v=v,edge[k].cap = cap,edge[k].cost = cost,edge[k].next = head[u],head[u] = k++;
    edge[k].u=v,edge[k].v=u,edge[k].cap = 0,edge[k].cost = -cost,edge[k].next = head[v],head[v] = k++;
}
void init(){
    memset(head,-1,sizeof(head));
    tot = 0;
}
bool spfa(int s,int t,int n){
    memset(vis,false,sizeof(vis));
    for(int i=0;i<=n;i++){
        low[i] = (i==s)?0:INF;
        pre[i] = -1;
    }
    queue<int> q;
    q.push(s);
    while(!q.empty()){
        int u = q.front();
        q.pop();
        vis[u] = false;
        for(int k=head[u];k!=-1;k=edge[k].next){
            int v = edge[k].v;
            if(edge[k].cap>0&&low[v]>low[u]+edge[k].cost){
                low[v] = low[u] + edge[k].cost;
                pre[v] = k; ///v爲終點對應的邊
                if(!vis[v]){
                    vis[v] = true;
                    q.push(v);
                }
            }
        }
    }
    if(pre[t]==-1) return false;
    return true;
}
int MCMF(int s,int t,int n){
    int mincost = 0,minflow,flow=0;
     while(spfa(s,t,n))
    {
        if(low[t]>=0) break;
        minflow=INF+1;
        for(int i=pre[t];i!=-1;i=pre[edge[i].u])
            minflow=min(minflow,edge[i].cap);
        flow+=minflow;
        for(int i=pre[t];i!=-1;i=pre[edge[i].u])
        {
            edge[i].cap-=minflow;
            edge[i^1].cap+=minflow;
        }
        mincost+=low[t]*minflow;
    }
    total=flow;
    return mincost;
}

int main()
{
    int n,m,h,tcase;
    while(scanf("%d%d",&n,&m)!=EOF){

        init();
        int s = 0,t = n+1;
        for(int i=1;i<=n;i++){
            //if(a[i]>=mx) b[i] = 0;
            int a,b,c,d;
            scanf("%d%d%d%d",&a,&b,&c,&d);
            addEdge(s,i,b,a,tot);
            addEdge(i,t,d,-c,tot);
        }
        for(int i=1;i<=m;i++){
            int u,v,w;
            scanf("%d%d%d",&u,&v,&w);
            addEdge(u,v,INF,w,tot);
            addEdge(v,u,INF,w,tot);
        }
        long long ans = MCMF(s,t,n+1);
        cout<<-ans<<endl;
    }
    return 0;
}
相關文章
相關標籤/搜索