版权声明:本文为博主原创文章,转载请说明出处。 https://blog.csdn.net/xianpingping/article/details/83240390
差分约束
1.构图方式:
就是利用不等式和最短路中的性质,通过建图得到的一种最优解,
例如,最短路中有dist[u]>=dist[v]+w(v,u)那么就类似:A-B<=C,移项得: 建边(B,A,C) .
2.难点:难点就在于这种题一般不会裸的告诉你什么关系,总是要根据题目分析出来不等关系后才能进行建边和差分约束的应用。一般有负权存在的时候都采用spfa算法,如果没有的话,优化的dij算法是最优的。
2.例题(shui):
poj3169—奶牛的题目:
就是n头奶牛,给了几种关系,问1-n奶牛最远距离。
代码:
#include<iostream>
#include<string.h>
#include<algorithm>
#include<vector>
#include<queue>
#include<stdio.h>
using namespace std;
const int maxn=1010;
const int inf=0x3f3f3f3f;
struct node
{
int v,cost;
node(int _v=0,int _cost=0):v(_v),cost(_cost){}
};
vector<node>G[maxn];
void add(int u,int v,int w){
G[u].push_back(node(v,w));
}
bool vis[maxn];
int dist[maxn];
int cnt[maxn];
bool spfa(int start,int n){
memset(vis,0,sizeof(vis));
for(int i=1;i<=n;i++){ dist[i]=inf;}
dist[start]=0;
vis[start]=1;
queue<int>que;
while(!que.empty()) que.pop();
que.push(start);
memset(cnt,0,sizeof(cnt));
cnt[start]=1;
while(!que.empty()){
int u=que.front();
que.pop();
vis[u]=false;
for(int i=0;i<G[u].size();i++){
int v=G[u][i].v;
if(dist[v]>dist[u]+G[u][i].cost){
dist[v]=dist[u]+G[u][i].cost;
if(!vis[v]){
vis[v]=1;
que.push(v);
if(++cnt[v]>n)
return false;
///有负权回路
}
}
}
}
return true;
}
int n,ml,md;
int main()
{
int x,y,z;
while(scanf("%d%d%d",&n,&ml,&md)!=EOF){
/// cout<<inf<<endl;
memset(G,0,sizeof(G));
for(int i=1;i<=ml;i++){
scanf("%d%d%d",&x,&y,&z);
add(x,y,z);
}
for(int i=1;i<=md;i++){
scanf("%d%d%d",&x,&y,&z);
add(y,x,-z);
}
if(spfa(1,n)==false){///有负权回路
cout<<"-1"<<endl;
}
else if(dist[n]==inf){
cout<<"-2"<<endl;
}
else{
cout<<dist[n]<<endl;
}
}
return 0;
}
/*
4
3 0
1 3 -2
3 2 1
1 2 3
*/