最短路&差分约束

很久以前还有过一篇floyd和dijkstra的东西虽然写得丑也放上来吧

floyd

多源最短路,k要放在外面。

for(k=1;k<=n;k++)
	for(i=1;i<=n;i++)
		for(j=1;j<=n;j++)
			dist[i][j]=min(dist[i][j],dist[i][k]+dist[k][j]);

dijkstra

用优先队列维护,不能有负权边。

memset(dist,0x3f,sizeof(dist));
dist[1]=0; q.push(PLI(0,1)); //priority_queue
while(!q.empty())
{
	int u=q.top().second;
	LL di=q.top().first;
	q.pop();
	if(di>dist[u]) continue;
	for(int i=0;i<G[u].size();i++)
	{
		int v=G[u][i].first,w=G[u][i].second;
		if(dist[v]>dist[u]+w)
		{
			dist[v]=dist[u]+w;
			q.push(PLI(dist[v],v));
		}
	}
}

spfa

用队列存储可以松弛其他点的点,代码自行参考下面代码建完图之后的部分。

还可以用dfs来写,求负环会比较好。

void dfs(int u,double x)
{
	vis[u]=true;
	for(node *p=head[u];p!=NULL;p=p->nxt)
	{
		int v=p->v;
		double w=p->w-x;
		if(dist[v]>dist[u]+w)
		{
			if(vis[v]) { f=true; break; }
			dist[v]=dist[u]+w;
			dfs(v,x);
		}
	}
	vis[u]=false;
}

差分约束

1.定义

如果一个系统由n个变量和m个约束条件组成,形成m个形如 a i − a j ≤ k a_i-a_j≤k aiajk的不等式( i , j ∈ [ 1 , n ] i,j∈[1,n] i,j[1,n],k为常数),则称其为差分约束系统(system of difference constraints)。亦即,差分约束系统是求解关于一组变量的特殊不等式组的方法。

2.求解

求解差分约束系统,可以转化成图论的单源最短路径(或最长路径)问题。

观察不等式 a i − a j ≤ k a_i-a_j≤k aiajk,可以成为 a i ≤ k + a j a_i≤k+a_j aik+aj,长得就像求最短路时的松弛操作。所以对于每个不等式,可以建一条从j到i的有向边,边权为k。

如果符号不是≤,那就转化啊。
a i − a j ≥ k a_i-a_j \ge k aiajk可以转化为 a j − a i ≤ − k a_j-a_i \le -k ajaik
a i − a j < k a_i-a_j \lt k aiaj<k可以转化为 a i − a j ≤ k − 1 a_i-a_j \le k-1 aiajk1
a i − a j = k a_i-a_j = k aiaj=k可以转化为 a i − a j ≤ k , a i − a j ≥ k a_i-a_j \le k,a_i-a_j \ge k aiajk,aiajk(然后再继续转化一下即可)。

如果要求最大值,那么转化为≤,跑最短路;如果要求最小值,那么转化为≥,跑最长路。

跑最短路时,如果发现负环,就说明题目给的信息矛盾,不等式组无解;
如果到达不了,就说明有变量没有被约束。

以下是bzoj1731的代码(就当一个写得比较丑的板子):

#include
#include
#include
#include
#include
#define maxn 1005
#define LL long long
#define INF 0x3f3f3f3f
using namespace std;
struct node { int v,w; };
int n,ml,md,dist[maxn],cnt[maxn];
bool inq[maxn];
vector<node> G[maxn];
queue<int> q;
int main()
{
	scanf("%d%d%d",&n,&ml,&md);
	for(int i=2;i<=n;i++)
	{
		node p;
		p.v=i-1,p.w=0;
		G[i].push_back(p);
	}
	for(int i=1;i<=ml;i++)
	{
		int u; node p;
		scanf("%d%d%d",&u,&p.v,&p.w);
		G[u].push_back(p);
	}
	for(int i=1;i<=md;i++)
	{
		int u; node p;
		scanf("%d%d%d",&p.v,&u,&p.w);
		p.w=-p.w;
		G[u].push_back(p);
	}
	memset(dist,0x3f,sizeof(dist));
	dist[1]=0,inq[1]=true,cnt[1]=1;
	q.push(1);
	while(!q.empty())
	{
		int u=q.front();q.pop();
		inq[u]=false;
		for(int i=0;i<G[u].size();i++)
		{
			int v=G[u][i].v,d=G[u][i].w;
			if(dist[v]>dist[u]+d)
			{
				dist[v]=dist[u]+d;
				if(!inq[v])
				{
					cnt[v]++;
					q.push(v);inq[v]=true;
					if(cnt[v]>=n) { printf("-1\n"); return 0; }
				}
			}
		}
	}
	printf("%d\n",dist[n]==INF?-2:dist[n]);
}

题目:bzoj1731

你可能感兴趣的:(一些(玄学的)知识,图论)