1. 程式人生 > >BZOJ 2330 [SCOI2011]糖果

BZOJ 2330 [SCOI2011]糖果

差分 ans style {0} long long stream -- sha 反向

題解:差分約束

怎麽才可以卡掉Spfa與正反向建邊的關系

在不T的情況下要多入隊幾次才能判出負環

出題人SangxinBingkuang

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
typedef long long Lint;
const Lint oo=10000000000000;
const int maxn=300009;


int n,m;
long long ans=0;

int cntedge=0;
int head[maxn]={0};
int to[maxn<<1]={0},nex[maxn<<1]={0};
Lint dist[maxn<<1]={0};
void Addedge(int x,int y,Lint z){
	nex[++cntedge]=head[x];
	to[cntedge]=y;
	dist[cntedge]=z;
	head[x]=cntedge;
}


int s;
queue<int>q;
int inq[maxn]={0};
Lint d[maxn];
int t[maxn];
int Spfa(){
	for(int i=1;i<=n;++i)d[i]=-oo;
	d[s]=0;inq[s]=1;q.push(s);
	while(!q.empty()){
		int x=q.front();q.pop();inq[x]=0;
		for(int i=head[x];i;i=nex[i]){
			if(d[x]+dist[i]>d[to[i]]){
				d[to[i]]=d[x]+dist[i];
				if(!inq[to[i]]){
					if(++t[to[i]]==500)return 0;
					q.push(to[i]);
					inq[to[i]]=1;
				}
			}
		}
	}
	return 1;
}

int main(){
	scanf("%d%d",&n,&m);
	s=n+1;
	while(m--){
		int opty,x,y;
		scanf("%d%d%d",&opty,&x,&y);
		if(opty==1){
			Addedge(x,y,0);
			Addedge(y,x,0);
		}
		if(opty==2){
			Addedge(x,y,1);
		}
		if(opty==3){
			Addedge(y,x,0);
		}
		if(opty==4){
			Addedge(y,x,1);
		}
		if(opty==5){
			Addedge(x,y,0);
		}
	}
	for(int i=n;i>=1;--i)Addedge(s,i,1);
	if(!Spfa()){
		printf("-1\n");
		return 0;
	}else{
		for(int i=1;i<=n;++i)ans+=d[i];
		printf("%lld\n",ans);
	}
	return 0;
}

  

BZOJ 2330 [SCOI2011]糖果