题目描述 Description
小 K 在 Minecraft 里面建立很多很多的农场,总共 n 个,以至于他自己都忘记了每个农场中种植作物的具体数量了,他只记得一些含糊的信息(共 m 个),以下列三种形式描述:
1. 农场 a 比农场 b 至少多种植了 c 个单位的作物。
2. 农场 a 比农场 b 至多多种植了 c 个单位的作物。
3. 农场 a 与农场 b 种植的作物数一样多。
但是,由于小 K 的记忆有些偏差,所以他想要知道存不存在一种情况,使得农场的种
植作物数量与他记忆中的所有信息吻合。
输入格式:
第一行包括两个整数 n 和 m,分别表示农场数目和小 K 记忆中的信息数目。
接下来 m 行:
如果每行的第一个数是 1,接下来有 3 个整数 a,b,c,表示农场 a 比农场 b 至少多种植
了 c 个单位的作物。
如果每行的第一个数是 2,接下来有 3 个整数 a,b,c,表示农场 a 比农场 b 至多多种植
了 c 个单位的作物。如果每行的第一个数是 3,家下来有 2 个整数 a,b,表示农场 a 终止的
数量和 b 一样多。
输出格式:
如果存在某种情况与小 K 的记忆吻合,输出“Yes”,否则输出“No”。
输入样例:
3 3
3 1 2
1 1 3 1
2 2 3 2
输出样例:
Yes
数据范围
对于 100% 的数据保证:1 ≤ n,m,a,b,c ≤ 10000。
差分约束裸题,对于第一种情况,建一条 a 到 b 权值为 -c 的边,第二种情况,建一条 b 到 a 权值为 c 的边,第三种情况,建一条 a 和 b 间 权值为 0 的双向边,然后跑最短路判负环或者跑最长路判正环就好,数据好像卡spfa,裸spfa会 T 几个点,要加个 SLF 优化,至于代码里注掉的那两行qwq,那两行要慎用233,如果 SLF 都过不了的话,去掉 SLF 加那两行说不定会有奇效(真 · 黑科技)233。
#include<iostream>
#include<cstdio>
#include<deque>
#include<cstring>
using namespace std;
const int size = 200010;
int head[size],next[size],dist[size];
bool use[size];
int tot = 1,n,m;
struct dc
{
int t,d;
}l[size];
deque < int > q;
inline void build(int f,int t,int d)
{
l[tot].t = t;
l[tot].d = d;
next[tot] = head[f];
head[f] = tot ++;
}
int tim[size];
inline bool spfa(int s)
{
for(register int i = 1 ; i <= n ; i ++)
dist[i] = 214748364;
dist[s] = 0;
use[s] = 1;
q.push_back(s);
while(!q.empty())
{
int f = q.front();
q.pop_front();
use[f] = 0;
for(register int i = head[f] ; i ; i = next[i])
{
int t = l[i].t;
if(dist[t] > dist[f] + l[i].d)
{
dist[t] = dist[f] + l[i].d;
if(!use[t])
{
tim[t] ++;
if(tim[t] > n)
return false;
use[t] = 1;
if(!q.empty())
{
if(dist[t] < dist[q.front()])
q.push_front(t);
// else if(t > q.front())
// q.push_front(t);
else
q.push_back(t);
}
else
q.push_back(t);
}
}
}
}
return true;
}
int main()
{
scanf("%d%d",&n,&m);
for(register int i = 1 ; i <= m ; i ++)
{
int ins;
scanf("%d",&ins);
int f,t,d;
if(ins == 1)
{
scanf("%d%d%d",&f,&t,&d);
build(f,t,-d);
}
else if(ins == 2)
{
scanf("%d%d%d",&f,&t,&d);
build(t,f,d);
}
else
{
scanf("%d%d",&f,&t);
build(f,t,0);
build(t,f,0);
}
}
for(register int i = 1 ; i <= n ; i ++)
build(0,i,0);
if(spfa(0))
puts("Yes");
else
puts("No");
return 0;
}