2017"百度之星"程序设计大赛 - 初赛(B)1005.度熊的交易计划【最小费用流】

度度熊的交易计划

 
 Accepts: 460
 
 Submissions: 2329
 Time Limit: 12000/6000 MS (Java/Others)
 
 Memory Limit: 32768/32768 K (Java/Others)
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

思路:


很裸的一个最小费用流的问题.


我们建图:

①建立源点,连入各个节点,花费为-c【i】,流为d【i】。

②建立汇点,将各个节点连入汇点,花费为a【i】,流为b【i】。

③将图的边(u,v)加到网络中,花费为w,流为INF。


然后连续最短路跑费用流就行了,值得注意的一个坑点是,我们如果从源点到汇点的距离大于0的时候,我们这条边如果走过去了就相当于赔钱了。

所以当dis【tt】>0的时候,我们终止跑费用流。


Ac代码:

#include
using namespace std;
struct node
{
    int from;
    int to;
    int w;
    int f;
    int num;
    int next;
}e[2000000];
int dist[505][505];
int head[10000];
int vis[10000];
int dis[10000];
int pre[10000];
int path[10000];
int n,m,kk,cont,ss,tt;
void add(int from,int to,int f,int w)
{
    e[cont].to=to;
    e[cont].f=f;
    e[cont].w=w;
    e[cont].num=cont;
    e[cont].next=head[from];
    head[from]=cont++;
}
int SPFA()
{
    for(int i=1;i<=tt;i++)dis[i]=0x3f3f3f3f;
    dis[ss]=0;
    memset(vis,0,sizeof(vis));
    queues;
    s.push(ss);
    while(!s.empty())
    {
        int u=s.front();
        s.pop();
        vis[u]=0;
        for(int i=head[u];i!=-1;i=e[i].next)
        {
            int v=e[i].to;
            int w=e[i].w;
            int f=e[i].f;
            if(f&&dis[v]>dis[u]+w)
            {
                dis[v]=dis[u]+w;
                pre[v]=u;
                path[v]=e[i].num;
                if(vis[v]==0)
                {
                    vis[v]=1;
                    s.push(v);
                }
            }
        }
    }
    if(dis[tt]>0)return 0;
    else return 1;
}
void MCMF()
{
    int ans=0;
    int maxflow=0;
    while(SPFA()==1)
    {
        int minn=0x3f3f3f3f;
        for(int i=tt;i!=ss;i=pre[i])
        {
            minn=min(e[path[i]].f,minn);
        }
        for(int i=tt;i!=ss;i=pre[i])
        {
            e[path[i]].f-=minn;
            e[path[i]^1].f+=minn;
        }
        ans+=minn*dis[tt];
        maxflow+=minn;
    }
    printf("%d\n",-ans);
}
int main()
{
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        ss=n+1;
        tt=ss+1;
        cont=0;
        memset(head,-1,sizeof(head));
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                dist[i][j]=0x3f3f3f3f;
            }
            dist[i][i]=0;
        }
        for(int i=1;i<=n;i++)
        {
            int aa,bb,cc,dd;
            scanf("%d%d%d%d",&aa,&bb,&cc,&dd);
            add(ss,i,dd,-cc);
            add(i,ss,0,cc);
            add(i,tt,bb,aa);
            add(tt,i,0,-aa);
        }
        for(int i=1;i<=m;i++)
        {
            int x,y,w;
            scanf("%d%d%d",&x,&y,&w);
            dist[x][y]=min(dist[x][y],w);
            dist[y][x]=min(dist[y][x],w);
        }
        for(int i=1;i<=n;i++)
        {
            for(int j=1;j<=n;j++)
            {
                if(dist[i][j]==0x3f3f3f3f)continue;
                add(i,j,0x3f3f3f3f,dist[i][j]);
                add(j,i,0,-dist[i][j]);
            }
        }
        MCMF();
    }
}














你可能感兴趣的:(网络流相关,最短路及其拓展)