hdu 2448 Mining Station on the Sea

最小费用最大流。

多源多汇点,把源点S 到 每个船所在的station建一条容量为1,cost为0的单向边。

把每个port到 汇点T 建一条容量为1,cost为1的但单向边。

注意station之间的边的容量要建为inf。。

而且port 和 station之间是单向边。开始建的双向,WA死了,搜题解全是最短路+KM = = 害的我都怀疑我的想法了。

题目这句话 Notice that once the ship entered the port, it will not come out!

说明,船不能经过一个port 到达另外一个port。。。

#include <set>
#include <map>
#include <queue>
#include <stack>
#include <math.h>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include <limits.h>
#include <string.h>
#include <string>
#include <algorithm>
#define MID(x,y) ( ( x + y ) >> 1 )
#define L(x) ( x << 1 )
#define R(x) ( x << 1 | 1 )
#define BUG puts("here!!!")

using namespace std;

const int MAX = 310;
const int LALA = 200000;
struct NODE{  
    int from,to,cap,cost;  
    int next;  
};  
NODE node[LALA];  			// 根据题意 
int p[MAX];  				// 相当于指针数组 
int cou,n,m;  
void init()  
{  
    memset(p,-1,sizeof(p));    
    cou = 2;    			// 初始化为偶数 
}  
void Add(int u,int v,int cap,int cost)  
{  
    node[cou].from = u;  
    node[cou].to = v;  
    node[cou].cap = cap;  
    node[cou].cost = cost;  
    node[cou].next = p[u];  
    p[u] = cou++;  
      
    node[cou].from = v;  
    node[cou].to = u;  
    node[cou].cap = 0;  
    node[cou].cost = -cost;  
    node[cou].next = p[v];  
    p[v] = cou++;  
}  
int MincostMaxflow(int s,int t,int n )  
{  
    queue<int> q;  
    int inq[MAX],pre[MAX],dis[MAX],re[MAX];  
    int u,v,i,a,c = 0,ind,cost,cap;  
    while(1)  
    {  
        memset(inq,0,sizeof(inq));  
        fill(dis,dis+MAX,INT_MAX);
        dis[s] = 0;  
        inq[s] = 1;  
        pre[s] = s;  
        q.push(s);  
        while( !q.empty() )  
        {  
            u = q.front();  
            q.pop();  
            inq[u] = 0;  
            ind = p[u];  
            while( ind != -1 )  
            {  
                u = node[ind].from;  
                v = node[ind].to;  
                cost = node[ind].cost;  
                cap = node[ind].cap;  
                if( cap > 0 && dis[v] > dis[u] + cost )  
                {  
                    dis[v] = dis[u] + cost;  
                    pre[v] = u;  
                    re[v] = ind;  
                    if( !inq[v] )  
                    {  
                        q.push(v);  
                        inq[v] = 1;  
                    }  
                }  
                ind = node[ind].next;     
            }  
        }  
        if( dis[t] == INT_MAX ) break; 
        a = INT_MAX;  
        for(u=t; u!=s; u=pre[u])  
            if( node[re[u]].cap < a )    
                a = node[re[u]].cap;  
        for(u=t; u!=s; u=pre[u])  
        {  
            node[re[u]^1].cap += a;   
            node[re[u]].cap -= a;  
        }  
        c += dis[t]*a;  
    }  
    return c;  
}  

int main()
{
	int n, m, k, pp, from, to, len;
	int S, T;
	
	while( ~scanf("%d%d%d%d", &n, &m, &k, &pp) )
	{
		S = 0;
		T = n + m + 1;
		init();
		for(int i=0; i<n; i++)
		{
			scanf("%d", &to);
			Add(S, to, 1, 0);
		}
		
		while( k-- )
		{
			scanf("%d%d%d", &from, &to, &len);
			Add(from, to, m, len);
			Add(to, from, m, len);
		}
		
		while( pp-- )
		{
			scanf("%d%d%d", &from, &to, &len);
			Add(to, from + m, 1, len);
		}
		
		for(int i=1; i<=n; i++)
			Add(i + m, T, 1, 0);

		int ans = MincostMaxflow(S, T, n + m + 2);
		printf("%d\n", ans);
	}

return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值