差分约束

差分约束1
差分约束2
差分约束3
差分约束(洛谷题解)

对于差分约束其实就是求最短(长)路的过程
x1-x2<=7…1
x2-x3<=3…2
x1-x3<=9…3
求(x1-x3)max=?
要同时满足1 2 3三个式子 => 求交集
1+2=>(x1-x3max=10
3=>( x1-x3 )max=9
(x3-x1)max=9

  • if(dis[v]<=dis[u]+w) dis[v]=dis[u]+w;
    相当于求最长路
    —> x3-x1<=9
    —> x3<=x1+9


P1993

P1993 小K的农场(差分约束模板)

for(register int i=1;i<=n;i++){
	add(0,i,0);
}
  • 判 断
    图中有环时则不存在(不存在 a>b && b>c && c>a )
    ——>最短路判负环
    ——>最长路判正环
    BFS

此题卡BFS,只有60分,超时(T_T)

inline int spfa(){
	queue<int> que;
    memset(dis, -0x3f, sizeof(dis));
    dis[0]=0;
	vis[0]=1;
	que.push(0);
    while(!que.empty()){
        int find=que.front();
        cnt[find]++;
        if(cnt[find]>=n){//判断条件
        	flag=0;
        	break;
        }
        que.pop();  
		vis[find]=0;
        for(int i=head[find];i!=0;i=e[i].next){
        	int u=e[i].from;
        	int v=e[i].to;
        	int w=e[i].weight;
            if(dis[u]+w>dis[v]){
                dis[v]=dis[find]+w;
                if(!vis[v]){
                	vis[v]=1;
					que.push(v);
                }       
            }
		}
    }
    return flag;
}
int main(){
	if(!spfa()) printf("No");
	else printf("Yes");
}
DFS
inline int spfa(int u){
    vis[u]=1;
    for(int i=head[u];i;i=e[i].next)
    	int v=edge[i].to;
    	int w=edge[i].weight;
        if(dis[v]<dis[u]+w){
            dis[v]=dis[u]+w;
            if(vis[v])return 0;
            if(!spfa(v))return 0;
        }
    vis[u]=0;
    return 1;
}
int main(){;
	if(!spfa(0))cout<<"No";
    else cout<<"Yes";
	return 0;
}


P1250

P1250
——>https://www.cnblogs.com/BigYellowDog/p/11231829.html

  • 建 图

每个部分为一个单位尺寸大小并最多可种一棵树
也就是说一个位置至多只能种1棵树。把它抽象成不等式:
0 <= dis[x] - dis[x - 1] <= 1

  • 代 码
#include<queue>
#include<cstdio>
#include<cctype>
#include<cstring>
#include<cstdlib>
using namespace std;
int op,a,b,c,n,dis[10001],l[10001],tot,m,flag;
struct node{
	int next,to,w;
}e[60001];
inline void add(int u,int v,int w){
	e[++tot]=(node){l[u],v,w};l[u]=tot;return;
};
bool vis[10001];
int read(){
    int x = 0; char c = getchar();
    while(c < '0' || c > '9') c = getchar();
    while(c >= '0' && c <= '9') {
    	x = x * 10 + c - '0'; c = getchar();
    }
    return x;
}
inline void spfa(){
	queue<int> que;
    memset(dis, -0x3f, sizeof(dis));
    dis[n + 1] = 0, vis[n + 1] = 1, que.push(n + 1);
    while(!que.empty()){
        int now = que.front();
        que.pop();  vis[now] = 0;
        for(int i = l[now]; i != 0; i = e[i].next)
            if(dis[now] + e[i].w > dis[e[i].to]){
                dis[e[i].to] = dis[now] + e[i].w;
                if(!vis[e[i].to])
                    vis[e[i].to] = 1, que.push(e[i].to);
            }
    }
}
int main(){
	n=read();m=read();
	for(int i=1;i<=n;i++){
		dis[i]=0x7fffffff;
	}
	while(m--){
		a=read();b=read();op=read();
		add(a-1,b,op);
	}
	dis[0]=0;
	int nn=n;
	while(nn>=0){add(n+1,nn,0),n--;}//
	nn=1;
	while(nn<=n){add(nn-1,nn,0),add(nn,nn-1,-1);}//
	spfa();
	printf("%d",dis[n]);
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值