首先不要被题目吓倒,这题你就做出大半了。
只有联通块内才会互相约束(废话)
扫描每一个联通块,找到一个起点,假设他的权值为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; }