usaco布局(差分约束系统的应用)

题目的正解

很明显可以看出是差分约束系统的题目,1:如果A和B距离至多为D则建边A->B权值为D,2:距离至少为D则建边B->A权值为-D。然后最短路。若有负权环则输出-1,若无法到达点N则输出-2,否则直接输出1~N的距离即可。

代码

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<string>
#include<cmath>
#include<queue>

using namespace std;

const int maxn=2002;
const int inf=0x3f3f3f3f;

struct
{
	int pre,v,c;
}edge[1000009];

int kk,head[maxn],ml,mn,dist[maxn],y[maxn],n;
bool b[maxn];
void addedge(int u,int v,int c)
{
	kk++;edge[kk].v=v;edge[kk].c=c;edge[kk].pre=head[u];head[u]=kk;
}
int main()
{
	scanf("%d%d%d",&n,&ml,&mn);
	for (int i=1;i<=ml;i++)
	{
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		addedge(a,b,c);
	}
	for (int i=1;i<=mn;i++)
	{
		int a,b,c;
		scanf("%d%d%d",&a,&b,&c);
		addedge(b,a,-c); 
	}//建图
	bool k=true;
	queue<int> q;
	memset(dist,inf,sizeof(dist));
	dist[1]=0;y[1]=1;b[1]=true;
	q.push(1);
	while (!q.empty())
	{
		int r=q.front();
		q.pop();
		for (int i=head[r];i;i=edge[i].pre)
		{
			int vv=edge[i].v,cc=edge[i].c;
			if (dist[r]+cc<dist[vv])
			{
				dist[vv]=dist[r]+cc;
				if (!b[vv]) 
				{
					y[vv]++;
					if (y[vv]==n) //判断负环
					{
						k=false;
						break;
					}
					b[vv]=true;
					q.push(vv);
				}
			}
		}
		if (!k) break;
		b[r]=false;
	} // spfa最短路
	if (!k) printf("-1");
	else if (dist[n]!=inf) printf("%d",dist[n]);
	else printf("-2");
	return 0;
}



你可能感兴趣的:(usaco布局(差分约束系统的应用))