标签:des blog http os io strong for ar
| Time Limit: 4000MS | Memory Limit: 65536K | |
| Total Submissions: 13531 | Accepted: 4635 | 
Description
Input
Output
Sample Input
1 3 3 1 1 1 0 1 1 1 2 2 1 0 1 1 2 3 1 1 1 2 1 1 1 1 1 3 2 20 0 0 0
Sample Output
4 -1
给出的物品的种类太多,不同的供应商对不同的店家供应不同的货物的花费不同,这样是同一个图中的边太多,直接建图会超时,所以,对每一种货物分别建图,求出每一种的货物的最小花费,得到最终的花费
感谢http://blog.csdn.net/scf0920/article/details/38707085
#include <cstdio>
#include <cstring>
#include <queue>
#include <algorithm>
using namespace std;
#define maxn 60
#define INF 0x3f3f3f3f
struct node
{
    int v , w , s ;
    int next ;
} p[100000];
int nk[maxn][maxn] , mk[maxn][maxn] , cnt ;//nk存储不同的店家对不同货物的需求,mk,不同的供应商对不同货物的供应量
int head[maxn<<2] , vis[maxn<<2] , dis[maxn<<2] , pre[maxn<<2] ;
queue <int> q ;
void add(int u,int v,int w,int s)
{
    p[cnt].v = v ;
    p[cnt].w = w ;
    p[cnt].s = s ;
    p[cnt].next = head[u] ;
    head[u] = cnt++ ;
    p[cnt].v = u ;
    p[cnt].w = 0 ;
    p[cnt].s = -s ;
    p[cnt].next = head[v] ;
    head[v] = cnt++ ;
}
int spfa(int s,int t)
{
    int u , v , i ;
    memset(dis,INF,sizeof(dis));
    vis[s] = 1 ; dis[s] = 0 ;
    pre[s] = pre[t] = -1 ;
    while( !q.empty() )
        q.pop();
    q.push(s);
    while( !q.empty() )
    {
        u = q.front();
        q.pop();
        vis[u] = 0 ;
        for(i = head[u] ; i != -1 ; i = p[i].next)
        {
            v=  p[i].v ;
            if( p[i].w && dis[v] > dis[u] + p[i].s )
            {
                dis[v] = dis[u] + p[i].s ;
                pre[v] = i ;
                if( !vis[v] )
                {
                    vis[v] = 1 ;
                    q.push(v);
                }
            }
        }
    }
    if( pre[t] == -1 )
        return 0;
    return 1 ;
}
int f(int s,int t,int k)
{
    int ans_s = 0 , ans_w = 0 , min1 , i ;//ans_s存储最小花费,ans_w存储一共的流量
    memset(vis,0,sizeof(vis));
    memset(pre,-1,sizeof(pre));
    while( spfa(s,t) )
    {
        min1 = INF ;
        for(i = pre[t] ; i != -1 ; i = pre[ p[i^1].v ])
            if( p[i].w < min1 )
                min1 = p[i].w ;
        for(i = pre[t] ; i != -1 ; i = pre[ p[i^1].v ])
        {
            p[i].w -= min1 ;
            p[i^1].w += min1 ;
            ans_s += min1*p[i].s ;
        }
        ans_w += min1 ;
    }
    if(ans_w == nk[0][k])
        return ans_s ;
    return -1;
}
int main()
{
    int i , j , n , m , kk , k , x , ans , flag ;//输入很复杂,尤其是不同的供应商对不同的店家供应不同的货物有不同的价格。
    while(scanf("%d %d %d", &n, &m, &k) && n+m+k != 0)
    {
        /*建图方式,对每种货物分别建图,对于第ki种货物的建图:由源点到每个供应商(容量是供应的货物的量,花费是0),由供应商到店家(容量是INF,花费是供应ki货物的价格)
        ,有店家到汇点建图(容量是店家需要的货物的量,花费是0)*/
        memset(nk,0,sizeof(nk));
        for(i = 1 ; i <= n ; i++)
            for(j = 1 ; j <= k ; j++)
            {
                scanf("%d", &nk[i][j]);
                nk[0][j] += nk[i][j] ;//nk[0][]储存下一共需要第j样货物的数量
            }
        for(i = 1 ; i <= m ; i++)
            for(j = 1 ; j <= k ; j++)
                scanf("%d", &mk[i][j]);
        ans = flag = 0 ;//flag判断之前的货物是不是都可以供应足够,如果不够,不用向下在计算。
        for(kk = 1 ; kk <= k ; kk++)
        {
            cnt = 0 ;
            memset(head,-1,sizeof(head));
            for(i = 1 ; i <= m ; i++)
                add(0,i,mk[i][kk],0);
            for(i = 1 ; i <= n ; i++)
                add(m+i,m+n+1,nk[i][kk],0);
            for(i = 1 ; i <= n ; i++)
                for(j = 1 ; j <= m ; j++)
                {
                    scanf("%d", &x);
                    add(j,m+i,INF,x);
                }
            if(flag != -1)
            {
                flag = f(0,n+m+1,kk);
                if(flag != -1)
                    ans += flag ;
            }
        }
        if(flag == -1)
            printf("-1\n");
        else
            printf("%d\n", ans);
    }
    return 0;
}
 
poj2516--Minimum Cost(费用流,分别建图),布布扣,bubuko.com
poj2516--Minimum Cost(费用流,分别建图)
标签:des blog http os io strong for ar
原文地址:http://blog.csdn.net/winddreams/article/details/38711797