差分约束合集 II

hdu 3440 House Man

题意巨烦,看懂了也就是一般的差分约束问题。
需要注意的是:最短路的spfa使得到的值尽可能大,最长路的spfa使得到的值尽可能小
在这题中,我们用st和ed表示最矮、最高两座塔。最后所有的塔的位置均能在一条坐标轴上表示。若ed的值小于st(ed在st的左边),则以st为源点的spfa得到的结果中,ed和st两点的距离会最小。因为st为0且固定,ed必小于0。基于最短路spfa的原则,ed会尽可能大。意味着st和ed间的距离越小。
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
#include<queue>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
// http://acm.hdu.edu.cn/showproblem.php?pid=3440
const int MAXN = 1005;
const int INF = 1000000010;
struct node 
{
	int v, next;
	int w;
}ee[MAXN*MAXN];
int head[MAXN], ne;
int n, dis[MAXN], dd;
bool vis[MAXN], instk[MAXN];
void add(int u, int v, int w)
{
	ee[ne].v = v; ee[ne].w = w; ee[ne].next = head[u];
	head[u] = ne++;
}
bool spfa(int u)
{
	if (instk[u]) return 0;
	instk[u] = 1;
	vis[u] = 1;
	for (int i=head[u]; ~i; i=ee[i].next)
	{
		int v = ee[i].v;
		if (dis[v] > dis[u]+ee[i].w)
		{
			dis[v] = dis[u]+ee[i].w;
			if (!spfa(v)) return false;
		}
	}
	instk[u] = 0;
	return 1;
}
int judge(int st, int ed)
{
	memset(vis, 0, sizeof vis);
	memset(instk, 0, sizeof instk);
	for (int i = 0; i< n ; ++i) dis[i] = INF;
	dis[st] = 0;
	for (int i = 0; i< n; ++i)
	{
		if (!vis[i])
		{
			if (!spfa(i)) return -1;
		}
	}
	return dis[ed]-dis[st];
}
struct qs
{
	int w, id;
	bool operator < (const qs & a) const
	{
		return w < a.w;
	}
}da[MAXN];
int solve()
{
	for (int i = 0; i< n-1; ++i)
 	{
	 	int a = da[i].id, b = da[1+i].id;    		
	 	if (a-b > dd || a-b < -dd) return -1;
	 	if ( a > b) add(b, a, dd);
	 	else add(a, b, dd);
	 	add(i+1, i, -1);
   	}
   	if (da[0].id < da[n-1].id)
   		return judge(da[0].id, da[n-1].id);
	else
		return judge(da[n-1].id, da[0].id);
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif    
	int t, cs = 0;
	scanf("%d", &t);
    while (t--)
    {
    	printf("Case %d: ", ++cs);
    	scanf("%d%d", &n, &dd);
    	memset(head, -1, sizeof head); ne = 0;
    	for (int i = 0; i< n; ++i)
    	{
	    	scanf("%d", &da[i].w);
	    	da[i].id = i;
	    }
	    sort(da, da+n);
	    printf("%d\n", solve()); 
    }
    return 0;
}


hdu 1384 Intervals

学到一个教训,spfa的dfs不能乱用。
在有判断负环的spfa中,dfs必bfs快。但是在这题里不存在负环,所以常规的bfs解法更快,且dfs会超时
#include<cstdio>
#include<algorithm>
#include<vector>
#include<cmath>
#include<queue>
#pragma comment(linker, "/STACK:1024000000,1024000000")
using namespace std;
// http://acm.hdu.edu.cn/showproblem.php?pid=1384
const int MAXN = 50010;
const int INF = 0x3f;
struct node 
{
	int v, next;
	int w;
}ee[MAXN*10];
int head[MAXN], ne;
int dis[MAXN], m;
bool vis[MAXN];
void add(int u, int v, int w)
{
	ee[ne].v = v; ee[ne].w = w; ee[ne].next = head[u];
	head[u] = ne++;
}
int spfa(int st, int ed)
{
	memset(vis, 0, sizeof vis);
	memset(dis, INF, sizeof dis);
	queue<int> qq;
	qq.push(ed);
	vis[ed] = 1; dis[ed] = 0;
	while (!qq.empty())
	{
		int u = qq.front(); qq.pop();
		vis[u] = 0;
		for (int i = head[u]; ~i; i= ee[i].next)
		{
			int v = ee[i].v;
			if (dis[v] > dis[u]+ee[i].w)
			{
				dis[v] = dis[u]+ee[i].w;
				if(!vis[v])
				{
					vis[v] = 1;
					qq.push(v);
				}
			}
		}
	}
	return dis[ed]-dis[st];
}
int main()
{
#ifndef ONLINE_JUDGE
    freopen("in.txt", "r", stdin);
#endif    
	while (scanf("%d", &m) != EOF)
	{
		memset(head, -1, sizeof head); ne = 0;
		int mn = 1000000, mx = -1;
		for (int i = 0; i< m; ++i)
		{
			int a, b, c;
			scanf("%d%d%d", &a, &b, &c);
			++a, ++b;
			add(b, a-1, -c);
			mn = min(a,mn); mx = max(mx,b);
		}
		for (int i = mn; i<= mx; ++i)
		{
			add(i, i-1, 0);
			add(i-1, i, 1);
		}
		printf("%d\n", spfa(mn-1, mx));
	}
    return 0;
}


hdu 1531 King

水题,比较基础
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值