码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 1927 SDOI 2010 星际竞速 费用流

时间:2014-10-27 12:56:03      阅读:185      评论:0      收藏:0      [点我收藏+]

标签:bzoj   sdoi2010   费用流   edmondskarp   拆点   

题目大意:宇宙空间中进行了一次竞速大赛。有两种飞行方式,第一种是通过正常的道路,但是只能从标号小的飞到标号大的地方;第二种是直接过去,但是需要花费固定的时间。问正好遍历一次所有的点最少需要的多少时间。


思路:费用流。把每个点拆点,S到每个点的起点连费用0的边,向每个终点连费用为固定费用的边,图中原有的边从一个的起点连到另一个点的终点。然后每个点的终点向T连边。跑最小费用最大流就是最后的答案。


CODE:

#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAXP 1700
#define MAX 4000000
#define S 0
#define T (points << 1|1)
#define INF 0x3f3f3f3f
using namespace std;

int points,edges;
int head[MAXP],total = 1;
int next[MAX],aim[MAX],cost[MAX],flow[MAX];
int src[MAXP];

int f[MAXP],p[MAXP],from[MAXP];
bool v[MAXP];

inline void Add(int x,int y,int f,int c)
{
	next[++total] = head[x];
	aim[total] = y;
	flow[total] = f;
	cost[total] = c;
	head[x] = total;
}

inline void Insert(int x,int y,int f,int c)
{
	Add(x,y,f,c);
	Add(y,x,0,-c);
}

inline bool SPFA()
{
	static queue<int> q;
	while(!q.empty())	q.pop();
	q.push(S);
	memset(f,0x3f,sizeof(f));
	memset(v,false,sizeof(v));
	f[S] = 0;
	while(!q.empty()) {
		int x = q.front(); q.pop();
		v[x] = false;
		for(int i = head[x]; i; i = next[i])
			if(f[aim[i]] > f[x] + cost[i] && flow[i] > 0) {
				f[aim[i]] = f[x] + cost[i];
				if(!v[aim[i]]) {
					v[aim[i]] = true;
					q.push(aim[i]);
				}
				from[aim[i]] = x;
				p[aim[i]] = i;
			}
	}
	return f[T] != INF;
}

long long EdmondsKarp()
{
	long long re = 0;
	while(SPFA()) {
		int remain_flow = INF;
		for(int i = T; i != S; i = from[i])
			remain_flow = min(remain_flow,flow[p[i]]);
		for(int i = T; i != S; i = from[i]) {
			flow[p[i]] -= remain_flow;
			flow[p[i]^1] += remain_flow;
		}
		re += (long long)remain_flow * f[T];
	}
	return re;
}

int main()
{
	cin >> points >> edges;
	for(int x,i = 1; i <= points; ++i) {
		scanf("%d",&src[i]);
		Insert(0,i,1,0);
		Insert(0,i + points,1,src[i]);
		Insert(i + points,T,1,0);
	}
	for(int x,y,z,i = 1; i <= edges; ++i) {
		scanf("%d%d%d",&x,&y,&z);
		if(x > y)	swap(x,y);
		Insert(x,y + points,1,z);
	}
	cout << EdmondsKarp() << endl;
	return 0;
}


BZOJ 1927 SDOI 2010 星际竞速 费用流

标签:bzoj   sdoi2010   费用流   edmondskarp   拆点   

原文地址:http://blog.csdn.net/jiangyuze831/article/details/40504279

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!