BZOJ 2330 [SCOI2011]糖果

差分约束的裸题,虽然我不会。

第一次见差分约束还是之前考试看LLJ大佬写的,感觉十分神奇。

a==b||a>=b||a<=b时连0的边;

a>b,a<b时连1的边;

因为每个小朋友都要吃糖,增设源点向每个小朋友连1的边;

然后跑最长路;

注意,等于的时候要连双向边,spfa时要判负环。

然后十分神奇的是据说这题要卡spfa,加源点的时候连边要从n到1,不然会被卡。

我:LLJ大佬,什么时候别人要卡我的spfa怎么办呀?

LLJ大佬:你可以rand一下,给每条边设个优先值,按优先值加啊。

我:太强啦!

#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
#include<queue>
#include<vector>
typedef long long LL;
const int maxn=200000+299;
int fl,n,k,x,a,b,ecnt,fir[maxn],nxt[maxn*2],to[maxn*2],val[maxn*2],vis[maxn],in[maxn];
LL dis[maxn],ans;
using namespace std;
int read() {
    int aa=0;char cc=getchar();
    while(cc<'0'||cc>'9') cc=getchar();
    while(cc>='0'&&cc<='9') aa=aa*10+cc-'0',cc=getchar();
    return aa;
}
void add(int u,int v,int w) {
    nxt[++ecnt]=fir[u]; fir[u]=ecnt; to[ecnt]=v; val[ecnt]=-w;
}
void init() {
    n=read(); k=read();
    for(int i=n;i>=1;i--) add(n+1,i,1);
    for(int i=1;i<=k;i++) {
        //scanf("%d%d%d",&x,&a,&b);
        x=read(); a=read(); b=read();
        if(a==b&&x!=1&&x!=3&&x!=5) fl=1;
        else {
            if(x==1) add(b,a,0),add(a,b,0);
            if(x==2) add(a,b,1);
            if(x==3) add(b,a,0);
            if(x==4) add(b,a,1);
            if(x==5) add(a,b,0);
        }
    }
}
queue<int>que;
void spfa() {
    memset(dis,127,sizeof(dis));
    memset(vis,0,sizeof(vis));
    que.push(n+1); 
    vis[n+1]=1; dis[n+1]=0;
    while(!que.empty()) {
        int x=que.front();
        que.pop(); vis[x]=0;
        for(int i=fir[x];i;i=nxt[i]) {
            if(dis[to[i]]>dis[x]+val[i]) {
                dis[to[i]]=dis[x]+val[i];
                if(!vis[to[i]]) {
                    vis[to[i]]=1;
                    in[to[i]]++;
                    if(in[to[i]]>n) { ans=-1; return;}
                    que.push(to[i]);
                }            
            }
        }
    }
    for(int i=1;i<=n;i++) ans-=dis[i];
}
void work() {
    if(fl) ans=-1;
    else spfa();
    printf("%lld\n",ans);
}
int main()
{
    //freopen(".in","r",stdin);
    //freopen(".out","w",stdout);
    init();
    work();
    return 0;
}
View Code

 

posted @ 2017-09-20 10:37  啊宸  阅读(121)  评论(0编辑  收藏  举报