【差分约束】我爱你啊

我爱你啊 


 【题目描述】 


    呐,贵树真的是一个很帅的男孩子呢,所以好多女孩都给他写至少一封 
了情书。那每个女孩给了贵树写了多少情书呢?我们不知道,但是我们知 
道一些女孩子写情书数量的关系,你的任务是推断出贵树最少受到了多少 
情书。 


 【输入文件】 


    输入的第一行为两个整数N,K,表示一共N 个女孩,知道K 对关系 
    接下来K 行,每行三个整数t,A,B 
    如果t=1,则表示A  的情书和B 的情书数量一样 
    如果t=2,则表示A  的情书少于B 的情书数量 
    如果t=3,则表示A  的情书不少于B 的情书数量 
    如果t=4,则表示A  的情书多于B 的情书数量 
    如果t=5,则表示A  的情书不多于B 的情书数量 


 【输出文件】 


    一行,表示贵树满足这些关系时最少情况下收到情书的数量。 
    如果这些关系不可能同时被满足,则输出-1。 


 【样例输入】 


    5 7 
    1 1 2 
    2 3 2 
    4 4 1 
    3 4 5 
    5 4 5 
    2 3 5 
    4 5 1 


 【样例输出】 


    11 


 【数据规模】 


    对于30% 数据,保证N  ≤ 100 
    对于100% 数据,保证N  ≤ 100000 

    对于全部数据,保证1 ≤ t ≤ 5, 1 ≤ A, B  ≤ N 



狗血的题目描述。。

这是一道差分约束系统的题目。

虽然标准的差分约束是建负边,

可是建负边的同学都错了,只有我们建正边的对了。

当时WA90,没有用long long


我的差分约束比较奇葩,因为一开始没有想出来如何定权值,于是就没有定。。用的时候用判断的方法就好了。

另外加了两个防坑爹的,就是如果a>a或者a<a,就果断退出,事实证明这个防坑爹多过了三组


#include <iostream>
using std::cout;
//using std::cin;
#include <cstdlib>
#include <cstdio>
const long oo = 0x7fff0000;


struct tnode
{
	long index;
	long val;
	tnode* next;
};


tnode* dian[100002];
const long RANGE = 15000020;


long n;long k;
long cnt[100002];
long f[100002];
long l = 0;
long r = 0;
long que[RANGE];
bool used[100002];


bool ssii(long a,tnode* b)
{
/*	if (b->val == 1 && f[b->index]>f[a])
	{
		f[b->index] = f[a];
		return true;
	}*/
	if (b->val == 1 && f[b->index]<f[a])
	{
		f[b->index] = f[a];
		return true;
	}
	
	if (b->val == 2 && f[b->index]<=f[a])
	{
		f[b->index] = f[a]+1;
		return true;
	}
/*	if (b->val == 3 && f[b->index]>f[a])
	{
		f[b->index] = f[a];
		return true;
	}
	if (b->val == 4 && f[b->index]>=f[a])
	{
		f[b->index] = f[a]-1;
		return true;
	}*/
	if (b->val == 5 && f[b->index]<f[a])
	{
		f[b->index] = f[a];
		return true;
	}
	return false;
}


void spfa()
{
	while (l!=r)
	{
		l++;
		l%=RANGE;
 		long now=que[l];
		tnode* ths = dian[now];
		used[now] = false;
		while (ths)
		{
			if (ssii(now,ths))
			{	
				cnt[ths->index]++;
				if (cnt[ths->index]>n)
				{
					printf("-1");
					exit(0);
				}
				if (!used[ths->index])
				{
					used[ths->index] = true;
					r++;
					r %= RANGE;
					que[r] = ths->index;
				}
			}
			ths = ths->next;
		}
	}
}


void insert(long c,long a,long b)
{
	tnode* tmp = new tnode;
	tmp->val = c;
	tmp->index = b;
	tmp->next = dian[a];
	dian[a] = tmp;
}


int main()
{
	freopen("love.in","r",stdin);
	freopen("love.out","w",stdout);
	
	scanf("%ld%ld",&n,&k);
	if (k==0){printf("%ld",n);return 0;}//avoid 坑爹 
	for (long i=1;i<k+1;i++)
	{
		long c;long a;long b;
		scanf("%ld%ld%ld",&c,&a,&b);
		if ((c==2||c==4)&&a==b){printf("-1");return 0;}//avoid 坑爹 
		insert(c,a,b);
		long d;
		switch (c)
		{
			case 1:d = 1;break;
			case 2:d = 4;break;
			case 3:d = 5;break;
			case 4:d = 2;break;
			case 5:d = 3;break;
		}
		insert(d,b,a);
	}
	
	for (long i=1;i<n+1;i++)
	{
		f[i] = 1;
		r++;
		r%=RANGE;
		que[r] = i;
	}
	spfa();
	long long sum = 0;
	for (long i=1;i<n+1;i++)
	{
		sum += f[i];
	}
	
	cout << sum;
	return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值