差分约束 - 糖果「BZOJ2330」[SCOI2011]

传送门

分析

差分约束:
答案求最小值,不等式变形为“>=",跑最长路
答案求最大值,不等式变形为"<=",跑最短路

对于这道题,根据操作选择点连边
最后,不要忘了隐含条件:每个人至少分一个糖果,所以就是 d [ i ] &gt; = 1 d[i]&gt;=1 d[i]>=1 d [ i ] − 0 &gt; = 1 d[i]-0&gt;=1 d[i]0>=1
从0往 i 建一条边,权值为1

此题有坑,需注意:
1.特判,操作2,3给出的两个人相同
2.从0往外连边时,需要倒序连(不知道为什么,网上说是数据有一条链,但还是不明白啊,怎么会被卡了?)

今日份小总结

写代码就像写作文
要先设计出来(画一下流程)然后就可以知道哪些要封装
不是说边写边想,一定要想好了再写
调试永远比写代码耗时久
所以一定要在写的时候就思考好,规划好


Code
#include<bits/stdc++.h>
#define in read()
#define M 500009
#define N 200009
#define ll long long
using namespace std;
inline int read(){
    char ch;int f=1,res=0;
    while((ch=getchar())<'0'||ch>'9') if(ch=='-') f=-1;
    while(ch>='0'&&ch<='9'){
        res=(res<<3)+(res<<1)+ch-'0';
        ch=getchar();
    }
    return f==1?res:-res;
}
int n,m;
int d[N];
int nxt[M],to[M],head[N],w[M],ecnt=0;
void add(int x,int y,int z){
    nxt[++ecnt]=head[x];head[x]=ecnt;to[ecnt]=y;w[ecnt]=z;
}
int ok=0,cnt[N];
bool vis[N];
void spfa(int S){
    queue<int> q;q.push(S);d[S]=0;
    while(!q.empty()){
        int u=q.front();q.pop();vis[u]=0;
        for(int e=head[u];e;e=nxt[e]){
            int v=to[e];
            if(d[v]>d[u]+w[e]){
                d[v]=d[u]+w[e];
                if(!vis[v]) {
                    vis[v]=1;
                    cnt[v]++;
                    if(cnt[v]>n) {ok=1;return;}//bfs的判断
                    q.push(v);
                }
            }
        }
    }
}
int main(){
    memset(d,127,sizeof(d));
    n=in;m=in;
    int i,j,k;
    int a,b;
    for(i=n;i>=1;--i) add(0,i,-1);/一定要逆序
    for(i=1;i<=m;++i){
        int op=in;a=in;b=in;
        if(op==1){	add(b,a,0);add(a,b,0);	}/tepan
        if(op==2){  add(a,b,-1);if(a==b) return printf("-1"),0;	}
        if(op==3){  add(b,a,0); 	}
        if(op==4){  add(b,a,-1);if(a==b) return printf("-1"),0;   }
        if(op==5){  add(a,b,0);	    }
    }
    d[0]=0;
    spfa(0);
    if(ok) return printf("-1"),0;
    ll ans=0;
    for(i=1;i<=n;++i){
        ans+=1ll*d[i];
    }
    printf("%lld\n",-ans);
    return 0;
}cpp
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值