题目:
题意:
每个点都有一个权值
p
i
p_i
pi,每个边也有一个边权
w
i
w_i
wi,我们需要调小
p
i
p_i
pi,使得可以满足任意边的
p
u
+
p
v
=
w
i
p_u+p_v=w_i
pu+pv=wi
求操作后点权最大值和最小值
分析:
可以确定的,对于每个连通块我们只需要知道其中一个点的权值就可以确定所有点的权值了
先钦定一个点的权值为
x
x
x,可以得到关于其他点的一元一次方程
一个点的权值,需要满足
⩾
0
\geqslant 0
⩾0且
⩽
p
i
\leqslant p_i
⩽pi
当一个点有多个方程,我们就判断这些方程的解的三种情况:无穷解、唯一解、无解
无穷解显然对答案不会有影响
而唯一解我们需要做的是在得到
x
x
x的范围后判断是否在范围内
无解对于答案肯定是无解的
最后就按照得出的
x
x
x的范围的最大值和最小值代入连通块求解
代码:
#include<cstdio>
#include<string>
#include<cstring>
#include<iostream>
#include<cmath>
#define LL long long
using namespace std;
inline LL read() {
LL d=0,f=1;char s=getchar();
while(s<'0'||s>'9'){if(s=='-')f=-1; s=getchar();}
while(s>='0'&&s<='9'){d=d*10+s-'0'; s=getchar();}
return d*f;
}
int p[500500];
struct node{
int to,next,w;
}e[6000050];
int ls[6000050],cnt=0;
void add(int x,int y,int w)
{
e[cnt]=(node){y,ls[x],w};
ls[x]=cnt++;
return;
}
int tf[500500],T_T=0,l,r,len=0,lf[500500],lb[500500],cc=0;
void check(int k,int f,int b)
{
if((lf[k]!=f||lb[k]!=b)&&lf[k]&lb[k])
{
if(b==lb[k]&&lf[k]!=f) {T_T=1;return;}
if(b!=lb[k]&&lf[k]==f) {T_T=1;return;}
double d=(double)(b-lb[k])/(lf[k]-f);
if((b-lb[k])/(lf[k]-f)!=d) {T_T=1;return;}
if(d<l||d>r) {T_T=1;return;}
l=r=d;
}
lf[k]=f;lb[k]=b;
return;
}
void dfs(int u,int f,int b)
{
if(T_T) return;
lf[u]=f;lb[u]=b;
int a=ceil((double)-b/f),c=(LL)(p[u]-b)/f;
if(f<0) swap(a,c);
if(a>c) {T_T=1;return;}
l=max(l,a);r=min(r,c);
for(int i=ls[u];~i;i=e[i].next)
{
int v=e[i].to;
if(tf[v]) {check(v,f*(-1),e[i].w-b);continue;}
tf[v]=1;
dfs(v,f*(-1),e[i].w-b);
}
return;
}
LL ansl[500500],ansr[500500],s1,s2;
void ddfs(int u)
{
s1+=ansl[u];s2+=ansr[u];
for(int i=ls[u];~i;i=e[i].next)
{
int v=e[i].to;
if(tf[v]) continue;
tf[v]=1;
ansr[v]=e[i].w-ansr[u];
ansl[v]=e[i].w-ansl[u];
ddfs(v);
}
return;
}
LL ss=0;
int main()
{
freopen("diamond.in","r",stdin);
freopen("diamond.out","w",stdout);
memset(ls,-1,sizeof(ls));
int n=read(),m=read();
for(int i=1;i<=n;i++) ss+=p[i]=read();
for(int i=1;i<=m;i++)
{
int x=read(),y=read(),w=read();
add(x,y,w);add(y,x,w);
}
for(int i=1;i<=n;i++)
{
if(tf[i]) continue;
tf[i]=1;
cc=0;len=1;
l=0;r=p[i];
dfs(i,1,0);
if(T_T||l>r) return !printf("NIE");
ansl[i]=l;ansr[i]=r;
}
LL ansi=0,ansx=0;
memset(tf,0,sizeof(tf));
for(int i=1;i<=n;i++)
{
if(tf[i]) continue;
tf[i]=1;
s1=0;s2=0;
ddfs(i);
ansi+=(min(s1,s2));
ansx+=(max(s1,s2));
}
cout<<ss-ansx<<" "<<ss-ansi;
return 0;
}