首页 > 代码库 > BZOJ 2330 SCOI2011 糖果 差分约束

BZOJ 2330 SCOI2011 糖果 差分约束

题目大意:给定n个点和之间的大小关系,求每个点最少是多少(必须大于0)

差分约束系统,按照题目说的连边即可,记住少于和不少于的大小关系是不一样的

边集要开3倍 此外注意的是0到i的连边要从后往前连 不然TLE 坑B数据逗死我了

#include<queue>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define M 100100
using namespace std;
struct abcd{
	int to,f,next;
}table[M*3];
int head[M],tot;
int n,m;
long long ans;
int f[M],times[M];
bool v[M];
void SPFA()
{
	int i;
	static queue<int> q;
	memset(f,0xef,sizeof f);
	q.push(0);f[0]=0;
	while( q.size() )
	{
		int x=q.front();q.pop();
		v[x]=0;
		for(i=head[x];i;i=table[i].next)
			if(f[table[i].to]<f[x]+table[i].f)
			{
				f[table[i].to]=f[x]+table[i].f;
				times[table[i].to]=times[x]+1;
				if(times[table[i].to]>n+1)
				{
					puts("-1");
					exit(0);
				}
				if(!v[table[i].to])
					v[table[i].to]=1,q.push(table[i].to);
			}
	}
}
void Add(int x,int y,int z)
{
	table[++tot].to=y;
	table[tot].f=z;
	table[tot].next=head[x];
	head[x]=tot;
}
int main()
{
	int i,p,x,y;
	cin>>n>>m;
	for(i=1;i<=m;i++)
	{
		scanf("%d%d%d",&p,&x,&y);
		switch(p)
		{
			case 1:
				Add(x,y,0);
				Add(y,x,0);
				break;
			case 4:
				swap(x,y);
			case 2:
				Add(x,y,1);
				break;
			case 3:
				swap(x,y);
			case 5:
				Add(x,y,0);
				break;
		}
	}
	for(i=n;i;i--)
		Add(0,i,1);
	SPFA();
	for(i=1;i<=n;i++)
		ans+=f[i];
	cout<<ans<<endl;
}


BZOJ 2330 SCOI2011 糖果 差分约束