P2294 [HNOI2005]狡猾的商人
作者:互联网
一句话题意:
给出一堆三元组 \((u, v, w)\),意思是 \(v\) 到 \(u\) 这一块的和正好为 \(w\),求问这一堆三元组是否满足互相不冲突。
考虑去用前缀和维护,那么三元组就转化成了以下这个等式:
\[sum_v-sum_u=w \]将它拆分成两个不等式:
\[sum_v-sum_u\le=w,\ sum_v-sum_u\ge=w \]把两个不等式转成同号的就可以用差分约束做了,记得多测清空。
#include <stdio.h>
#include <algorithm>
#include <string.h>
#include <queue>
#define N 500005
using namespace std;
inline int read(){
char ch;int x=0, f=1;ch=getchar();
while(ch<'0'||ch>'9'){if(ch=='-') f=-1;ch=getchar();}
while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
return x*f;
}
int tot, h[N];
struct Edge{
int to, nxt, v;
}edge[N*3];
void add(int x, int y, int w){
edge[++tot].to=y, edge[tot].nxt=h[x];
edge[tot].v=w, h[x]=tot;
}
int n, m;
int dis[N], in[N], cnt[N];
bool SPFA(int s){
queue <int> q;
memset(dis, 0x3f, sizeof(dis));
q.push(s);dis[s]=0;cnt[s]=1;
while(!q.empty()){
int x=q.front();q.pop(), in[x]=0;
// printf("--%d %d\n", x, dis[x]);
for(int i=h[x]; i; i=edge[i].nxt){
int to=edge[i].to, w=edge[i].v;
if(dis[to]>dis[x]+w){
dis[to]=dis[x]+w;
if(!in[to]){
in[to]=1, cnt[to]++;
if(cnt[to]>=n+2) return 0;
q.push(to);
}
}
}
}
return 1;
}
int main(){
int T=read();
for(; T; T--){
n=read(), m=read();
tot=0;//多测清空
memset(h, 0, sizeof(h));
memset(cnt, 0, sizeof(cnt));
memset(in, 0, sizeof(in));
//sum[l-1]-sum[r]<=-w
//sum[r]-sum[l-1]<=w
for(int i=1; i<=n; i++) add(n+1, i, 0);
//超级源点
for(int i=1; i<=m; i++){
int l=read(), r=read(), w=read();
add(r, l-1, -w);add(l-1, r, w);
}
if(SPFA(n+1)) printf("true\n");
else printf("false\n");
}
return 0;
}
标签:cnt,ch,int,sum,memset,HNOI2005,狡猾,P2294,dis 来源: https://www.cnblogs.com/sizeof127/p/14615895.html