BZOJ 2330: [SCOI2011]糖果【差分约束】

2330: [SCOI2011]糖果

【题目描述】
传送门

【题解】

这题就是差分约束的裸题,建边然后刷正环就可以了。

代码如下

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define MAXN 100005
using namespace std;
int n,K,hd,tl,dst[MAXN],que[MAXN],Tim[MAXN];
long long Ans;
bool vis[MAXN];
int tot,lnk[MAXN],nxt[4*MAXN],son[4*MAXN],w[4*MAXN];
void Add(int x,int y,int z){son[++tot]=y,w[tot]=z,nxt[tot]=lnk[x],lnk[x]=tot;}
bool SPFA(int x){
    hd=0,que[tl=1]=x,Tim[x]=1;vis[x]=1;
    while(hd^tl){
        x=que[(++hd)%=MAXN];vis[x]=0;
        for(int j=lnk[x];j;j=nxt[j])
        if(dst[x]+w[j]>dst[son[j]]){
            dst[son[j]]=dst[x]+w[j];
            if(++Tim[son[j]]>=n) return 0;
            if(!vis[son[j]]) vis[son[j]]=1,que[(++tl)%=MAXN]=son[j];
        }
    }
    return 1;
}
int main(){
    #ifndef ONLINE_JUDGE
    freopen("prob.in","r",stdin);
    freopen("prob.out","w",stdout);
    #endif
    scanf("%d%d",&n,&K);
    for(int i=1;i<=K;i++){
        int opt,x,y;scanf("%d%d%d",&opt,&x,&y);
        if(opt==1) Add(x,y,0),Add(y,x,0);else
        if(opt==2){if(x==y){printf("-1\n");return 0;}Add(x,y,1);}else
        if(opt==3) Add(y,x,0);else
        if(opt==4){if(x==y){printf("-1\n");return 0;}Add(y,x,1);}else Add(x,y,0);
    }
    for(int i=n;i;i--) Add(0,i,1);
    if(!SPFA(0)) printf("-1\n");else{
        for(int i=1;i<=n;i++) Ans+=dst[i];
        printf("%lld\n",Ans);
    }
    return 0;
}
posted @ 2018-05-23 18:26  XSamsara  阅读(141)  评论(0编辑  收藏  举报