差分约束

wangyitong

2018-09-26 19:22:37

Personal

哇,没搞清楚这个,结果被黄牌题吊打。。。。 差分约束系统是用来解一些特殊的不等式。 就是把每个约束条件建边,然后跑最短路或者最长路。 例如:    $x_{i}$ $-$ $x_{j}$>=k; 那么就从j向i连一条长度为k的边;跑最长路。    $x_{i}$ $-$ $x_{j}$<=k; 那么就从j向i连一条长度为k的边;跑最短路。 对于不同的题,跑最短路和最长路是不一样的,要看约束条件。 例题:[p1250——种树](https://www.luogu.org/problemnew/show/P1250) 这题就是用前缀和列出不等式,然后全部变成$x_{i}$ $-$ $x_{j}$>=k这一类型,然后跑最长路就是最后的答案了。 ```cpp #include<cstdio> #include<algorithm> #include<iostream> #include<cstring> #include<queue> using namespace std; const int N=30005; int head[N]; bool used[N]; int dis[N],n,m,tot,x,y,z; struct node { int next,value,to; }edge[N*100]; void add(int x,int y,int z) { tot++; edge[tot].to=y; edge[tot].value=z; edge[tot].next=head[x]; head[x]=tot; } void spfa(int x) { memset(dis,-63,sizeof(dis)); queue<int>Q; Q.push(x); dis[x]=0; while(!Q.empty()) { int y=Q.front();Q.pop();used[y]=0; for(int i=head[y];i;i=edge[i].next) { if(dis[edge[i].to]<dis[y]+edge[i].value) { dis[edge[i].to]=dis[y]+edge[i].value; if(!used[edge[i].to]) { used[edge[i].to]=1; Q.push(edge[i].to); } } } } } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=m;i++) { scanf("%d%d%d",&x,&y,&z); add(x-1,y,z); } for(int i=1;i<=n;i++) { add(i-1,i,0); add(i,i-1,-1); } memset(used,0,sizeof(used)); spfa(0); printf("%d",dis[n]); return 0; } ``` 只要题意可以变成许多个限制条件,然后就可以用差分约束了。 注意一般要用spfa,因为会有负环。 有负环说明这个方程组无解。 顺便说一下,怎么判无解吧. 一个点被入队n次就说明出现负环了。 不要让我这个蒟蒻证明~~(不会)~~(逃