• POJ--2516--Minimum Cost【最小费用最大流】


    链接:http://poj.org/problem?id=2516

    题意:有k种货物,n个客户对每种货物有一定需求量,有m个仓库。每一个仓库里有一定数量的k种货物。然后k个n*m的矩阵,告诉从各个仓库到各个客户位置运送单位第k种货物所需的运费。问满足全部客户需求的最小费用,如满足不了全部客户,则输出-1。


    思路:题目有点绕。只是多看看也就理解了。这道题算是最小费用最大流的入门题吧,建图非常easy能想到,主要是存在k种货物。每条货物都要建一条路,同一时候处理起来不好写。并且路径也较多。只是能够对每种货物分开来算。数据比較小。给了4000ms,不会超时。对每一个n*m矩阵,对于此时的货物建图。把最小费用累加起来。

    假设有一种货物没法满足全部客户。即网络最大流不等于客户需求之和,则输出-1。

    建图:对于每种货物单独建图。一个超级源点连向每一个客户。弧为客户对当前这样的货物的需求量,权为0。每一个仓库连向超级汇点,弧为仓库中当前这样的货物的储存量,权为0。对于n*m的矩阵,相应的客户连向相应的仓库,弧为INF,权为运送单位货物的花费。

    这样的建图方式比較好想,之前也做过几道题是一样的思路。


    #include<cstring>
    #include<string>
    #include<fstream>
    #include<iostream>
    #include<iomanip>
    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    #include<queue>
    #include<map>
    #include<set>
    #include<vector>
    #include<stack>
    #include<ctime>
    #include<cstdlib>
    #include<functional>
    #include<cmath>
    using namespace std;
    #define PI acos(-1.0)
    #define MAXN 500100
    #define eps 1e-7
    #define INF 0x7FFFFFFF
    #define LLINF 0x7FFFFFFFFFFFFFFF
    #define seed 131
    #define mod 1000000007
    #define ll long long
    #define ull unsigned ll
    #define lson l,m,rt<<1
    #define rson m+1,r,rt<<1|1
    
    struct node{
        int u,v,w,cost,next;
    }edge[MAXN];
    int head[150],dist[150],pree[150],vis[150];
    int n,m,k,cnt,src,sink,ans;
    void add_edge(int a,int b,int c,int d){
        edge[cnt].v = b;
        edge[cnt].w = c;
        edge[cnt].cost = d;
        edge[cnt].next = head[a];
        head[a] = cnt++;
    }
    bool spfa(){
        int i,j;
        queue<int>q;
        q.push(src);
        memset(vis,0,sizeof(vis));
        for(i=0;i<=n+m+2;i++)   dist[i] = INF;
        dist[src] = 0;
        vis[src] = 1;
        while(!q.empty()){
            int u = q.front();
            q.pop();
            vis[u] = 0;
            for(i=head[u];i!=-1;i=edge[i].next){
                if(edge[i].w&&dist[u]!=INF&&dist[u]+edge[i].cost<dist[edge[i].v]){
                    dist[edge[i].v] = dist[u] + edge[i].cost;
                    pree[edge[i].v] = i;
                    if(!vis[edge[i].v]){
                        vis[edge[i].v] = 1;
                        q.push(edge[i].v);
                    }
                }
            }
        }
    //    for(i=0;i<=n+m+2;i++){
    //        cout<<dist[i]<<endl;
    //    }
    //    cout<<endl<<endl;
        if(dist[sink]<INF)  return true;
        return false;
    }
    int augment(){
        int i,j;
        int delta = INF;
        for(i=sink;i!=src;i=edge[j^1].v){
            j = pree[i];
            delta = min(delta,edge[j].w);
        }
        for(i=sink;i!=src;i=edge[j^1].v){
            j = pree[i];
            edge[j].w -= delta;
            edge[j^1].w += delta;
            ans += edge[j].cost * delta;
        }
        return delta;
    }
    
    int ntok[60][60],ktom[60][60];
    int main(){
        int i,j,k;
        int a,b,c,sum;
        while(scanf("%d%d%d",&n,&m,&k),n||m||k){
            ans = 0;
            for(i=1;i<=n;i++){
                for(j=1;j<=k;j++){
                    scanf("%d",&ntok[i][j]);
                }
            }
            for(i=1;i<=m;i++){
                for(j=1;j<=k;j++){
                    scanf("%d",&ktom[i][j]);
                }
            }
            src = n + m + 2;
            sink = n + m + 1;
            int ii;
            int flag = 0;
            for(i=1;i<=k;i++){
                memset(head,-1,sizeof(head));
                cnt = 0;
                sum = 0;
                int flow = 0;
                for(ii=1;ii<=n;ii++){
                    for(j=1;j<=m;j++){
                        scanf("%d",&a);
                        add_edge(ii,j+n,INF,a);
                        add_edge(j+n,ii,0,-a);
                    }
                }
                if(flag)    continue;
                for(ii=1;ii<=n;ii++){
                    add_edge(src,ii,ntok[ii][i],0);
                    add_edge(ii,src,0,0);
                    sum += ntok[ii][i];
                }
                for(ii=1;ii<=m;ii++){
                    add_edge(ii+n,sink,ktom[ii][i],0);
                    add_edge(sink,ii+n,0,0);
                }
                while(spfa()){
                    flow += augment();
                }
                if(flow!=sum)   flag = 1;
            }
            if(flag)    puts("-1");
            else    printf("%d
    ",ans);
        }
        return 0;
    }
    


  • 相关阅读:
    谈谈分布式事务之一:SOA需要怎样的事务控制方式
    asp.net创建自定义排序用户界面
    在ASP.NET 2.0中操作数据:在GridView的页脚中显示统计信息
    Url重写技术的运用(转)
    ASP.NET 对 SqlDataSource 控件使用参数
    正则表达式分支条件与分组
    向DWR传递参数和返回参数(转)
    一位软件工程师的6年总结(转)
    ASP.NET 2.0数据教程之二十六::排序自定义分页数据
    Table控件使用示例
  • 原文地址:https://www.cnblogs.com/yutingliuyl/p/7019112.html
Copyright © 2020-2023  润新知