Bzoj 1731 POJ 3169 Luogu P4878 Layout

Description:

有n头牛排在一排, 有ML个条件(x,y,w)表示x,y希望彼此之间的距离小于等于w,有MD个条件(x,y,w)表示x,y希望彼此之间的距离大于等于w.
问1号奶牛和N 号奶牛之间的距离最大为多少。无解输出-1,如果有合法方案,但n号点可以在无穷大输出-2.

Analysis:

第一个条件d[x]+w <= d[y],与最短路中的dis[y] >= dis[x] + w,可以把每头牛看做一个点,从x向y连一条边权为w的边;
同理,对于第二个条件,从y向x连一条边权为w的边,这样就可以直接跑最短路,如果出现了负环,那么就无解.

注意:图有可能不连通,因此要从超级源点0向其余点建一条权值为0的边,先从开始跑SPFA。

Code

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>
#define N 1100
#define INF 0x3f3f3f3f 
using namespace std;
struct edge
{
	int to,next,w;
} e[20021];
int head[N],vis[N],dis[N],cnt[N],num_edge,n,ml,md;
void SPFA(int s)
{
	queue<int> Q;
	memset(dis,0x3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	memset(cnt,0,sizeof(cnt));
	dis[s] = 0;
	Q.push(s);
	vis[s] = 1;
	while(!Q.empty())
	{
		int u = Q.front();
		Q.pop();
		vis[u] = 0;
		for(int i = head[u]; i; i = e[i].next)
		{
			int v = e[i].to;
			if(dis[v] > dis[u] + e[i].w)
			{
				dis[v] = dis[u] + e[i].w;
				if(!vis[v])
				{
					Q.push(v);
					vis[v] = 1;
					cnt[v]++;
				}
				if(cnt[v] > n)
				{
					printf("-1\n");
					exit(0);
				}
			}
		}
	}
}
void add(int u,int v,int w)
{
	e[++num_edge].next = head[u];
	e[num_edge].to = v;
	e[num_edge].w = w;
	head[u] = num_edge;
}
int main()
{
	scanf("%d%d%d",&n,&ml,&md);
	for(int i = 1;i <= n;++i) add(0,i,0);
	for(int i = 1;i <= ml;++i)
	{
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		add(a,b,c);
	}
	for(int i = 1;i <= md;++i)
	{
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		add(b,a,-c);
	}
	SPFA(0);// judge whether the graph is connected
	SPFA(1);
	if(dis[n] == INF) printf("-2\n");
	else printf("%d\n",dis[n]);
	return 0;
}

posted @ 2019-05-04 21:48  Zforw  阅读(11)  评论(0编辑  收藏  举报