hdu 3572 Task Schedule(dinic)

28 篇文章 0 订阅

最大流判断满流。这里的满流就是说是否对于题目要求的流量,当前的网络是否流过不溢出,简言之就是最大流>=题目给出的流量。

用dinic的妥妥的T了。原因是对于走过的边重复走了。解决方法是,下一次回到这个节点时走的就是剩下没走过的边。然后get了一个新技能,当前弧的概念,也简言之就是走过的边不再走,但是实现的话,首先确定head不能变,就拿一个临时数组cur来充当head,而cur的变化正好解决了走过的边不再走的问题(因为cur的值变了嘛)具体的话看代码,其实就是for( int &i = cur[u];.......)里面的&用上就行了。总之yyn的话来讲就是dinic不加不行,isap可有可无= =反正我是没体会到。网络渣.

// http://acm.hdu.edu.cn/showproblem.php?pid=3572
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<queue>
#include<iostream>

using namespace std;

const int N = 1105;
const int inf = 99999999;

struct node{
	int v, w, nxt;
}e[N*N];

int dep[N], head[N], cnt;
int cur[N];
int st, ed;
int n, m;
queue<int> q;

void init()
{
	memset( head, -1, sizeof( head ));
	st = cnt = 0;
	ed = 500 + n + 1;
}

void add( int u, int v, int w )
{
	e[cnt].w = w;
	e[cnt].v = v;
	e[cnt].nxt = head[u];
	head[u] = cnt++;
	
	e[cnt].w = 0;
	e[cnt].v = u;
	e[cnt].nxt = head[v];
	head[v] = cnt++;
}

bool bfs( )
{
	while( !q.empty( ) )
		q.pop();
	memset( dep, 0, sizeof( dep ));
	q.push(st);
	dep[st] = 1;
	while( !q.empty() )
	{
		int u = q.front();
		q.pop();
		if( u == ed )
			return 1;
		for( int i = head[u]; ~i; i = e[i].nxt )
		{
			int v = e[i].v;
			if( !dep[v] && e[i].w )
			{
				dep[v] = dep[u] + 1;
				q.push(v);
			}
		}
	}
	return 0;
}

int dinic(int u, int minflow)
{
	if( u == ed )
		return minflow;
	int tmp = 0;
	for( int &i = cur[u]; ~i; i = e[i].nxt )
	{
		int v = e[i].v;
		if( dep[v] == dep[u]+1 && e[i].w )
		{
			int flow = dinic(v, min(e[i].w, minflow - tmp));
			e[i].w -= flow;
			e[i^1].w += flow;
			tmp += flow;
			if( tmp == minflow )
				return tmp;
		}
	}
	return tmp;
}

int solve()
{
	int tmp = 0;
	while( bfs() )
	{
		memcpy( cur, head, sizeof cur );
		tmp += dinic(st, inf);
	}
	return tmp;
}

int main()
{
	int tot;
	int cas = 1;
	scanf("%d", &tot);
	while( tot-- )
	{
		init();
		scanf("%d%d", &n, &m);
		int u, v, w;
		int sum = 0;
		for( int i = 1; i <= n; i++ )
		{
			scanf("%d%d%d", &w, &u, &v);
			sum += w;
			add( st, i, w );
			for( int j = u; j <= v; j++ )
			{
				add( i, j + n, 1);
			}
		}
		for( int i = 1; i <= 500; i ++ )
		{
			add(i + n, ed, m);
		}
		int ans = solve();
		printf("Case %d: ", cas++);
		if( sum == ans )
			printf("Yes\n\n");
		else
			printf("No\n\n");
	}
	return 0;
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值