【洛谷P4878】布局

题目大意:给定一个长度为 N 的递增序列,有 M 组差分约束关系,求满足这些约束关系时,第一个数和第 N 个数的差是多少。

题解:首先,能否满足约束关系需要判断一下负环,若满足约束关系,再从第一个点 spfa 即可求出答案。大于小于号打反检查一个小时,好久没遇到这种错误了。。我枯了QAQ。。。。

代码如下

#include <bits/stdc++.h>
using namespace std;
const int maxv=1010;
const int maxe=1e5+10;
const int inf=0x7fffffff;

struct node{
	int nxt,to,w;
}e[maxe];
int tot=1,head[maxv];
inline void add_edge(int from,int to,int w){
	e[++tot]=node{head[from],to,w},head[from]=tot;
}

int n,ml,md,d[maxv],cnt[maxv];
bool in[maxv];

void read_and_parse(){
	scanf("%d%d%d",&n,&ml,&md);
	for(int i=1,a,b,c;i<=ml;i++){
		scanf("%d%d%d",&a,&b,&c);
		add_edge(a,b,c);
	}
	for(int i=1,a,b,c;i<=md;i++){
		scanf("%d%d%d",&a,&b,&c);
		add_edge(b,a,-c);
	}
	for(int i=1;i<=n;i++)add_edge(0,i,0);
	for(int i=2;i<=n;i++)add_edge(i,i-1,0);
}

bool check(){
	queue<int> q;
	memset(d,0x3f,sizeof(d));
	d[0]=0,in[0]=1,q.push(0);
	while(q.size()){
		int u=q.front();q.pop(),in[u]=0;
		if(cnt[u]>n)return 1;
		for(int i=head[u];i;i=e[i].nxt){
			int v=e[i].to,w=e[i].w;
			if(d[v]>d[u]+w){
				d[v]=d[u]+w,cnt[v]=cnt[u]+1;
				if(!in[v])in[v]=1,q.push(v);
			}
		}
	}
	return 0;
}
void spfa(){
	queue<int> q;
	fill(d+1,d+n+1,inf);
	memset(in,0,sizeof(in));
	d[1]=0,in[1]=1,q.push(1);
	while(q.size()){
		int u=q.front();q.pop(),in[u]=0;
		for(int i=head[u];i;i=e[i].nxt){
			int v=e[i].to,w=e[i].w;
			if(d[v]>d[u]+w){
				d[v]=d[u]+w;
				if(!in[v])in[v]=1,q.push(v);
			}
		}
	}
}

void solve(){
	if(check())return (void)puts("-1");
	spfa();
	if(d[n]==inf)puts("-2");
	else printf("%d\n",d[n]);
}

int main(){
	read_and_parse();
	solve();
	return 0;	
}
posted @ 2019-03-23 18:16  shellpicker  阅读(118)  评论(0编辑  收藏  举报