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;
}