欢迎访问~原文出处——博客园-zhouzhendong
去博客园看该题解
题目传送门 - BZOJ1202
题意概括
有一个数列,共n个数字。
告诉你m个区间和,问是否矛盾。
数据组数<=100, n<=100, m<=1000
题解
网上都说的并查集的,貌似挺快的。
我这里给出一个特殊的做法,复杂度O(T(m+n)),T为数据组数。
我们根据题目给出的信息建图,然后spfa判断。
对于输入的 a,b,c,我们建立(a,b+1,c)(b+1,a,-c)两条边。
如果一个点,之前已经被某一个点更新过一次,现在又被某一个点更新了,那么就矛盾了。
所以,每一个点只会被更新一次,每一条边也最多访问一次,所以复杂度是可以的。
但是不知道为什么跑了244MS……
代码
#include <cstring>
#include <algorithm>
#include <cstdio>
#include <cstdlib>
#include <cmath>
using namespace std;
const int N=100+5,M=2000+5;
struct Gragh{
int cnt,x[M],y[M],z[M],nxt[M],fst[N];
void set(){
cnt=0;
memset(fst,0,sizeof fst);
}
void add(int a,int b,int c){
x[++cnt]=a,y[cnt]=b,z[cnt]=c;
nxt[cnt]=fst[a],fst[a]=cnt;
}
}g;
int T,n,m,dis[N],vis[N],q[N],head,tail,qmod;
bool check(){
int x,y,z;
memset(dis,0,sizeof dis);
memset(vis,0,sizeof vis);
qmod=n+2;
for (int mon=1;mon<=n;mon++){
if (vis[mon])
continue;
head=tail=0;
q[tail=(tail+1)%qmod]=mon;
vis[mon]=1;
while (head!=tail){
x=q[head=(head+1)%qmod];
for (int i=g.fst[x];i;i=g.nxt[i]){
y=g.y[i],z=g.z[i];
if (!vis[y]){
vis[y]=1;
dis[y]=dis[x]+z;
q[tail=(tail+1)%qmod]=y;
continue;
}
if (dis[y]!=dis[x]+z)
return 0;
}
}
}
return 1;
}
int main(){
scanf("%d",&T);
while (T--){
scanf("%d%d",&n,&m);
g.set();
for (int i=1,a,b,c;i<=m;i++){
scanf("%d%d%d",&a,&b,&c);
if (a>b)
swap(a,b);
g.add(a,b+1,c);
g.add(b+1,a,-c);
}
puts(check()?"true":"false");
}
return 0;
}