ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[HDU4940]Destroy Transportation system

2020-12-19 16:01:13  阅读:208  来源: 互联网

标签:Transportation int Graph sum system return dep Destroy const


题目

点这里看题目。

分析

似乎没有思路?

还是从割入手。对于任意割 \([S,V-S]\) 和可行流 \(f\) ,都有 \(|f|\le c(S,V-S)\) 。

因此,如果从 \(V-S\) 流向 \(S\) ,并且边的容量都是 \(c(u,v)=D(u,v)+B(u,v)\) ,那么就有

\[|f|\le c(V-S,S)=\sum_{v\in V-S}\sum_{u\in S}D(v,u)+B(v,u) \]

另一方面,我们尝试让 \(f\) 满足:

\[\sum_{u\in S}\sum_{v\in V-S}D(u,v)\le |f| \]

事实上,在有下界限制的网络流中,若定义 \(c_l(S,V-S)=\sum_{u\in S}\sum_{v\in V-S}c_l(u,v)\) ,那么对于任意可行流 \(f\) 也有 \(c_l(S,V-S)\le f(S,V-S)=|f|\) 。我们给每条边设置下界 \(c_l(u,v)=D(u,v)\) 即可。

此时我们需要让两个条件同时成立,因此我们可以求解循环流。如果存在满足上下界的循环流 \(f\) ,那么就有两个条件同时成立,自然就说明对于所有割均有题目条件成立。

巧妙之处在于利用割和流量的不等关系,在割的容量关系之间插入一个流量这个中间变量,将题设限制变成了容量限制

不由得让我想起相似形的中间比代换。

代码

#include <cstdio>

const int INF = 0x3f3f3f3f;
const int MAXN = 1e4 + 5, MAXM = 1e5 + 5;

template<typename _T>
void read( _T &x )
{
	x = 0; char s = getchar(); int f = 1;
	while( s < '0' || '9' < s ) { f = 1; if( s == '-' ) f = -1; s = getchar(); }
	while( '0' <= s && s <= '9' ) { x = ( x << 3 ) + ( x << 1 ) + ( s - '0' ), s = getchar(); }
	x *= f;
}

template<typename _T>
void write( _T x )
{
	if( x < 0 ) putchar( '-' ), x = -x;
	if( 9 < x ) write( x / 10 );
	putchar( x % 10 + '0' );
}

template<typename _T>
_T MIN( const _T a, const _T b )
{
	return a < b ? a : b;
}

template<typename _T>
_T MAX( const _T a, const _T b )
{
	return a > b ? a : b;
}

struct Edge
{
	int to, nxt, c;
}Graph[MAXM << 1];

int q[MAXN];

int A[MAXN];

int head[MAXN], dep[MAXN], cur[MAXN];
int N, M, cnt = 1, tot;

void AddEdge( const int from, const int to, const int C )
{
	Graph[++ cnt].to = to, Graph[cnt].nxt = head[from], Graph[cnt].c = C;
	head[from] = cnt;
}

void AddE( const int from, const int to, const int C ) { AddEdge( from, to, C ), AddEdge( to, from, 0 ); }

bool BFS( const int S, const int T )
{
	int h = 1, t = 0;
	for( int i = 1 ; i <= tot ; i ++ ) dep[i] = INF;
	dep[q[++ t] = S] = 0;
	while( h <= t )
	{
		int u = q[h ++], v;
		for( int i = head[u] ; i ; i = Graph[i].nxt )
			if( Graph[i].c && dep[v = Graph[i].to] > dep[u] + 1 )
				dep[q[++ t] = v] = dep[u] + 1;
	}
	return dep[T] < INF;
}

int DFS( const int u, const int lin, const int T )
{
	if( u == T ) return lin;
	int used = 0, ret, v, c;
	for( int &i = cur[u] ; i ; i = Graph[i].nxt )
	{
		v = Graph[i].to, c = Graph[i].c;
		if( dep[v] == dep[u] + 1 && c && ( ret = DFS( v, MIN( lin - used, c ), T ) ) )
		{
			used += ret, Graph[i].c -= ret, Graph[i ^ 1].c += ret;
			if( used == lin ) break;
		}
	}
	if( used < lin ) dep[u] = INF;
	return used;
}

int Dinic( const int S, const int T )
{
	int f = 0;
	while( BFS( S, T ) )
	{
		for( int i = 1 ; i <= tot ; i ++ ) cur[i] = head[i];
		f += DFS( S, INF, T );
	}
	return f;
}

void Clean()
{
	cnt = 1, tot = N;
	for( int i = 1 ; i <= tot + 2 ; i ++ )
		head[i] = A[i] = 0;
}

int main()
{
	int T;
	read( T );
	for( int cas = 1 ; cas <= T ; cas ++ )
	{
		read( N ), read( M ), Clean();
		for( int i = 1 ; i <= M ; i ++ )
		{
			int a, b, l, d;
			read( a ), read( b ), read( l ), read( d );
			AddE( b, a, d ); A[a] -= l, A[b] += l;
		}
		int ned = 0;
		const int s = ++ tot, t = ++ tot;
		for( int i = 1 ; i <= N ; i ++ )
			if( A[i] < 0 ) AddE( s, i, - A[i] );
			else if( A[i] > 0 ) ned += A[i], AddE( i, t, A[i] );
		printf( "Case #%d: ", cas ); int val = Dinic( s, t );
		puts( val == ned ? "happy" : "unhappy" );
	}
	return 0;
}

标签:Transportation,int,Graph,sum,system,return,dep,Destroy,const
来源: https://www.cnblogs.com/crashed/p/14159476.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有