首先不要被题目吓倒,这题你就做出大半了。
只有联通块内才会互相约束(废话)
扫描每一个联通块,找到一个起点,假设他的权值为x。
那么每个连出去的边的终点权值为 w-x 。也就是说每个点上一定为kx+b(其中k=1或-1)
也许每个点会被扫描到多次,分以下几种情况
1、k1==k2,若b1!=b2无解,若b1==b2.......没有影响,继续running
2、k1!=k2,那么我们可以算出x的值,把这个值带入算出连通块里的点的值,判断有无解即可。
如果扫描途中没有遇到什么意外(就是1、2的情况)那么利用么个点i的不等式连立不等式组0<=ki x+bi<=pi解出x的范围
注意解集是否为空集,这里也可能出现无解。
最后我们可以看到代价是x的一次函数,也就是说最值在边界出取得,判断一下就好了。
复杂度O(n+m)
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
typedef long long LL;
const int Maxn=6000005, Max=500005;
int node[Maxn],next[Maxn],a[Max],q[Max],x,y,z,n,m,l,r,tot,i;
LL len[Maxn],dig[Max],w[Max],total,maxx,minx,cnt1,cnt2,dw,up,data,t;
bool v[Max],flag;
struct arr { int w,s; } d[Max],tmp;
int read(){
char ch=getchar();
int ret=0;
while (ch<'0' || ch>'9') ch=getchar();
while (ch>='0' && ch<='9')
{ret=ret*10+ch-'0'; ch=getchar();}
return ret;
}
void add(int x,int y,int z){
node[++tot]=y; next[tot]=a[x]; a[x]=tot; len[tot]=z;
node[++tot]=x; next[tot]=a[y]; a[y]=tot; len[tot]=z;
}
bool Judge(int x){
for (q[l=r=1]=x,total=0;l<=r;l++){
v[q[l]]=1;
if (dig[q[l]]<0 || dig[q[l]]>w[q[l]]) return 0;
total+=(LL)w[q[l]]-dig[q[l]];
for (int i=a[q[l]];i;i=next[i]){
if (dig[node[i]]==-1)
dig[ q[++r]=node[i] ]=len[i]-dig[ q[l] ];
else if (dig[q[l]]+dig[node[i]]!=len[i])
return 0;
}
}
return 1;
}
void bfs(int x){
d[x].w=0; d[x].s=1; v[x]=1;
for (q[l=r=1]=x,data=-1;l<=r;l++){
for (int i=a[q[l]];i;i=next[i]){
if (v[node[i]]){
tmp.w=len[i]-d[node[i]].w;
tmp.s=(d[node[i]].s^1);
if (tmp.s==d[q[l]].s){
if (tmp.w!=d[q[l]].w)
{flag=0; break;}
else continue;
} else
{
if (tmp.s==0) t=-1; else t=1;
if ( (d[q[l]].w-tmp.w)/t<0 ) {flag=0; break;}
if ( ( (d[q[l]].w-tmp.w)/t )%2!=0 ) {flag=0; break;}
else {data = (d[q[l]].w-tmp.w)/t/2; break;}
}
} else
{
d[node[i]].w=len[i]-d[q[l]].w;
d[node[i]].s=(d[q[l]].s^1);
v[q[++r]=node[i]]=1;
}
}
if (flag==0 || data>=0) break;
}
if (data>=0){
dig[x]=data;
if (Judge(x)){
minx+=total;
maxx+=total;
} else {flag=0;return;}
return;
}
if (flag==0) return;
dw=0; up=1000000000;
for (int i=1;i<=r;i++){
tmp=d[q[i]];
if (tmp.s==1){
up=min(up,(LL)w[q[i]]-tmp.w);
dw=max(dw,(LL)-tmp.w);
} else
{
up=min(up,(LL)tmp.w);
dw=max(dw,(LL)tmp.w-w[q[i]]);
}
}
if (up<dw){ flag=0; return; }
cnt1=cnt2=0;
for (int i=1;i<=r;i++){
if (d[q[i]].s==1){
cnt1+=(LL)w[q[i]]-(d[ q[i] ].w+dw);
cnt2+=(LL)w[q[i]]-(d[ q[i] ].w+up);
} else
{
cnt1+=(LL)w[q[i]]-(d[ q[i] ].w-dw);
cnt2+=(LL)w[q[i]]-(d[ q[i] ].w-up);
}
}
minx+=min(cnt1,cnt2);
maxx+=max(cnt1,cnt2);
}
int main(){
freopen("bez.in","r",stdin);
freopen("bez.out","w",stdout);
//scanf("%d%d",&n,&m);
n=read(); m=read();
for (i=1;i<=n;i++) w[i]=read(); //scanf("%d",&w[i]);
for (i=1;i<=m;i++){
//scanf("%d%d%d",&x,&y,&z);
x=read(); y=read(); z=read();
add(x,y,z);
}
memset(dig,-1,sizeof(dig));
for (i=1,flag=1;i<=n;i++)
if (!v[i]){
bfs(i);
if (flag==0) break;
}
if (flag==0) puts("NIE");
else printf("%I64d %I64d\n",minx,maxx);
return 0;
}