码迷,mamicode.com
首页 > 其他好文 > 详细

BZOJ 2330 [SCOI2011]糖果

时间:2017-09-20 12:08:51      阅读:240      评论:0      收藏:0      [点我收藏+]

标签:lap   怎么办   i++   bzoj   har   nbsp   裸题   math   closed   

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

第一次见差分约束还是之前考试看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

 

BZOJ 2330 [SCOI2011]糖果

标签:lap   怎么办   i++   bzoj   har   nbsp   裸题   math   closed   

原文地址:http://www.cnblogs.com/Achenchen/p/7560176.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!