差分约束Layout

题目

思路

很明显的差分约束板子

  • 如果需要求的是两个变量差的最大值,那么需要将所有不等式转变成<=的形式,建图后求最短路;
  • 如果需要求的是两个变量差的最小值,那么需要将所有不等式转化成>=,建图后求最长路。
    本题需要建超级原点使图联通,判掉不合法情况
  • 图中有负环不能到达

代码

#include<bits/stdc++.h>
using namespace std;
const int maxn=1000+10;
const int maxm=5000*10+10;
int n,m,k;
int head[maxn],ver[maxm],edge[maxm],Next[maxm],tot;
void add(int x,int y,int z){
	ver[++tot]=y,edge[tot]=z,Next[tot]=head[x],head[x]=tot;
}
int dis[maxn];
bool vis[maxn];
bool flag=0;
int cnt[maxn];
queue<int>q;
int spfa(int x){
	memset(dis,0x3f,sizeof(dis));
	memset(vis,0,sizeof(vis));
	dis[x]=0;vis[x]=1;q.push(x);cnt[x]++;
	while(!q.empty()){
		int u=q.front();q.pop();vis[u]=0;
		for(int i=head[u];i;i=Next[i]){
			int v=ver[i];
			if(dis[v]>dis[u]+edge[i]){
				dis[v]=dis[u]+edge[i];
				if(!vis[v]){
					cnt[v]++;
					if(cnt[v]>n+1)return -1;
					vis[v]=1;
					q.push(v);
				}
			}
		}
	}
	if(dis[n]==0x3f3f3f3f)return -2;
	return dis[n];
}
int main(){
	scanf("%d%d%d",&n,&m,&k);
	for(int i=1,x,y,z;i<=m;i++){
		scanf("%d%d%d",&x,&y,&z);
		if(x>y)swap(x,y);
		add(x,y,z);
	}
	for(int i=1,x,y,z;i<=k;i++){
		scanf("%d%d%d",&x,&y,&z);
		if(x>y)swap(x,y);
		add(y,x,-z);
	}
	for(int i=1;i<=n;i++){
		add(0,i,0);
	}
	for(int i=1;i<n;i++){
		add(i+1,i,0);
	}
	if(spfa(0)==-1){
		printf("-1
");
		return 0;
	}
	printf("%d
",spfa(1));
}
 

原文地址:https://www.cnblogs.com/soda-ma/p/13324935.html