差分约束
Posted liukx
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了差分约束相关的知识,希望对你有一定的参考价值。
如果一个不等式组由 n 个变量和 m 个约束条件组成,形成 m 个形如x[ j ]-x[ i ]≤k(i,j∈[1,n] 且 k 为常数)的不等式,则称其为差分约束系统。换句话说,差分约束系统就是求解一组变量的不等式组的算法。
连边后求最短路
将x[ j ]?−x[ i ]?≤k 变形为 x[ j ]?≤k+x[ i ]?,即从 i 到j 连一条边权为 k 的边。加入超级源点后求最短路,得到xi?≤0 所有 x 最大解。
连边后求最长路
将x[ j ]?−x[ i ]?≤k 变形为 x[ i ]? ≤ x[ j ]-k?,即从 j 到 i 连一条边权为 −k 的边。加入超级源点后求最长路,得到 xi?≥0 所有 x 最小解
1 #include<iostream> 2 #include<queue> 3 #include<cstdio> 4 #include<cstring> 5 using namespace std; 6 #define N 5005 7 #define M 11000 8 int n,m,cnt; 9 int head[N]; 10 struct edge{ 11 int to,w,nxt; 12 }e[M]; 13 void add(int u,int v,int w){ 14 e[++cnt].w=w; 15 e[cnt].to=v; 16 e[cnt].nxt=head[u]; 17 head[u]=cnt; 18 } 19 int dis[5005],tot[5005];//tot为入队次数 20 bool vis[N]; 21 queue<int>q; 22 bool spfa(){ 23 for(int i=1;i<=n;i++) dis[i]=0x7ffffff; 24 memset(vis,0,sizeof(vis)); 25 q.push(0);dis[0]=0;vis[0]=1; 26 while(q.size()){ 27 int u=q.front();q.pop(); 28 vis[u]=0; 29 for(int i=head[u];i;i=e[i].nxt){ 30 int v=e[i].to; 31 if(dis[v]>dis[u]+e[i].w){ 32 dis[v]=dis[u]+e[i].w; 33 if(!vis[v]){ 34 vis[v]=1;q.push(v); 35 } 36 tot[v]++; 37 if(tot[v]==n)return 0; 38 } 39 } 40 } 41 return 1; 42 } 43 int main(){ 44 scanf("%d%d",&n,&m); 45 for(int i=1;i<=n;i++)add(0,i,0); 46 for(int i=1;i<=m;i++){ 47 int a,b,c; 48 scanf("%d%d%d",&a,&b,&c); 49 add(b,a,c); 50 } 51 if(!spfa()) 52 printf("NO"); 53 else 54 for(int i=1;i<=n;i++) 55 printf("%d ",dis[i]); 56 return 0; 57 }
例题:
https://www.luogu.com.cn/problem/P1250
poj1201
(也可用贪心和线段树优化)
跑最长路
1 #include<bits/stdc++.h> 2 using namespace std; 3 const int N = 1000005; 4 const int M = 1000005; 5 int n,m; 6 int dis[N]; 7 bool vis[N]; 8 int head[N],num; 9 struct Edge{ 10 int to,next,w; 11 }e[M]; 12 void add(int u,int v,int w){ 13 e[++num].w=w; 14 e[num].to=v; 15 e[num].next=head[u]; 16 head[u]=num; 17 } 18 void spfa(int x){ 19 queue<int> q; 20 q.push(x); 21 for(int i=0;i<=n+1;i++)dis[i]=1; 22 dis[x]=0;vis[x]=1; 23 while(!q.empty()){ 24 int u=q.front();q.pop(); 25 vis[u]=0; 26 for(int i=head[u];i;i=e[i].next){ 27 int v=e[i].to; 28 if(dis[v]>dis[u]+e[i].w){ 29 dis[v]=dis[u]+e[i].w; 30 if(!vis[v]){ 31 q.push(v); 32 vis[v]=1; 33 } 34 } 35 } 36 } 37 } 38 int main(){ 39 int a,b,c,minn=0x3f3f3f3f; 40 memset(head,-1,sizeof(head)); 41 cin>>n>>m; 42 int y=n+1; 43 for(int i=0;i<=n;i++) add(y,i,0); 44 for(int i=1;i<=m;i++){ 45 cin>>a>>b>>c; 46 add(b,a-1,-c); 47 } 48 for(int i=1;i<=n;i++){ 49 add(i-1,i,1); 50 add(i,i-1,0); 51 } 52 spfa(y); 53 for(int i=0;i<=n;i++) 54 minn=min(minn,dis[i]); 55 cout<<dis[n]-minn<<endl; 56 return 0; 57 }
以上是关于差分约束的主要内容,如果未能解决你的问题,请参考以下文章