【Luogu 3275】[SCOI2011]糖果

Luogu P3275
显然是一道经典的差分约束系统
相关知识可以查看:【Luogu 1993】差分约束系统问题——小K的农场
值得注意的是这题使用最长路更合适,因为每一个人都要取得至少一个糖果。在添加超级起点时,这本身就是一个使用大于等于号的关系,如果更换成小于等于号则会导致边的方向改变,这样又违背了超级起点的初衷。

#include<cstdio>
#include<algorithm>
using namespace std;
struct data
{
	int to,next,val;
}e[500005];
int cost[500005],flag,head[500005],n,m,a,b,c,cnt,x,cnt1[500005],p=500005;
class queue
{
    int x[5000005],head,tail;
public:
    void push(int y)
    {
    	x[tail]=y;
		tail++;
		tail%=p;
    }
    void pop()
    {
        head++;
        head%=p;
    }
    bool empty()
    {
        return head==tail;
    }
    int back()
    {
        return x[tail-1];
    }
    int front()
    {
        return x[head];
    }
}que;
bool vis[500005];
void add(int u,int v,int w)
{
	e[++cnt].to=v;
	e[cnt].next=head[u];
	e[cnt].val=w;
	head[u]=cnt;
}
void First(int s)
{
	for (int i=1;i<=n;i++) cost[i]=-0x3f3f3f3f;
	cost[s]=0;
}
bool SPFA(int s)
{
	que.push(s);
	vis[s]=true;
	while (!que.empty())
	{
		int now=que.front();
		que.pop();
		vis[now]=false;
		for (int i=head[now];i;i=e[i].next)
		{
			if (cost[e[i].to]<cost[now]+e[i].val)
			{
				cost[e[i].to]=cost[now]+e[i].val;
				if (!vis[e[i].to])
				{
					que.push(e[i].to);
					vis[e[i].to]=true;
				}
				cnt1[e[i].to]=cnt1[now]+1;
				if (cnt1[e[i].to]>n) return false;
			}
		}
	}
	return true;
}
int main()
{
	scanf("%d%d",&n,&m);
	for (int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&x,&a,&b);
		if (x==1) add(a,b,0),add(b,a,0);
		if (x==2) 
		{
			if (a==b) 
			{
				printf("-1");
				return 0;
			}
			add(a,b,1);
		}
		if (x==3) add(b,a,0);
		if (x==4) 
		{
			add(b,a,1);
			if (a==b) 
			{
				printf("-1");
				return 0;
			}
		}
		if (x==5) add(a,b,0);
		//特判可以防止TLE
	}
	for (int i=n;i>=1;i--)
		add(n+1,i,1);//反向是为了防TLE,数据比较特别……
	First(n+1);
	if (!SPFA(n+1)) printf("-1");
	else
	{
		long long ans=0;
		for (int i=1;i<=n;i++) 
			ans+=cost[i];
		printf("%lld",ans);
	}
	return 0;
}
posted @ 2019-11-28 21:56  Nanjo  阅读(102)  评论(0编辑  收藏  举报