BZOJ_2801_[Poi2012]Minimalist Security_dfs树+特判+乱搞

Description

给出一个N个顶点、M条边的无向图,边(u,v)有权值w(u,v),顶点i也有权值p(i),
并且对于每条边(u,v)都满足p(u)+p(v)>=w(u,v)。
现在要将顶点i的权值减去z(i),其中0<=z(i)<=p(i)。
修改后设顶点i的权值p'(i)=p(i)-z(i),对于每条边(u,v)都满足p'(u)+p'(v)=w(u,v)。
求sum{z(i)}的最小值和最大值。

Input

第一行两个正整数n,m (n<=500,000, m<=3,000,000)。
第二行n个整数,依次表示p(1),p(2),...,p(n) (0<=p(i)<=10^6)。
下面m行,每行三个整数u,v,w (1<=u,v<=n, 0<=w<=10^6),表示存在一条权值为w的边(u,v)。

Output

两个正整数,分别表示sum{z(i)}的最小值和最大值,如果不存在方案就输出NIE。

Sample Input

For the input data:
3 2
5 10 5
1 2 5
2 3 3
the correct result is:
12 15
whereas for the following input data:
3 3
1 1 1
1 2 1
1 3 1
3 2 1
the correct result is:
NIE

考虑每个联通块,只有确定一个的值就能全部确定。
只考虑树上的边,然后给根一个权值0判非树边合法的做法是对的吗?
如果图中只有偶环这个做法是对的,并且在此基础上我们能求出根节点每增加一整棵树是加还是减。
同时确定每条边的范围(最少根节点要加几和最多根节点能加几),然后答案就能确定。
现在有了奇环,有什么影响?
考虑两个端点是同时加减的,也就是不能染色判非树边无解。
但反过来考虑,我们知道了这两个端点的和,同时因为同加减,两个端点的差也确定了,直接可以确定这两个点。
 
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cstdlib>
using namespace std;
typedef long long ll;
#define N 500050
#define M 3000050
#define GG puts("FUCK")
int cnt,n,m,head[N],to[M<<1],nxt[M<<1],val[M<<1],a[N];
int Q[N],l,r,L[N],R[N],b[N],c[N],vis[N],dep[N],qwq[N],d[N],S[N],ls,rs;
inline char nc() {
static char buf[100000],*p1,*p2;
return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
}
int rd() {
int x=0; char s=nc();
while(s<'0'||s>'9') s=nc();
while(s>='0'&&s<='9') x=(x<<3)+(x<<1)+s-'0',s=nc();
return x;
}
inline void add(int u,int v,int w) {
to[++cnt]=v; nxt[cnt]=head[u]; head[u]=cnt; val[cnt]=w;
}
int ok;
ll ans1,ans2,suma,sumb,s1,s2;
int lmax,rmin;
void dfs(int x) {
int i; vis[x]=1;
suma+=a[x]; sumb+=b[x];
if(!c[x]) L[x]=(b[x]>=0?0:-b[x]),R[x]=a[x]-b[x];
else L[x]=(b[x]<=a[x]?0:b[x]-a[x]),R[x]=b[x];
lmax=max(lmax,L[x]);
rmin=min(rmin,R[x]);
if((b[x]<0&&c[x])||(b[x]>a[x]&&!c[x])) {
puts("NIE"); exit(0);
}
c[x]?s2++:s1++;
for(i=head[x];i;i=nxt[i]) {
int y=to[i];
if(ok) return ;
if(!vis[y]) {
dep[y]=dep[x]+1;
b[y]=val[i]-b[x]; c[y]=c[x]^1;
dfs(y);
}else {
if((dep[x]-dep[y])%2) {
// printf("%d %d\n",dep[x],dep[y]);
if(b[y]+b[x]!=val[i]) {
puts("NIE"); exit(0);
}
}else {
// GG;
ok=1;
if((b[x]-b[y]+val[i])&1) {
puts("NIE"); exit(0);
}
// printf("%d %d\n",x,y);
if(qwq[x]&&d[x]!=(b[x]-b[y]+val[i])/2) {
puts("NIE"); exit(0);
}
d[x]=(b[x]-b[y]+val[i])/2;
if(qwq[y]&&d[y]!=val[i]-d[x]) {
puts("NIE"); exit(0);
}
d[y]=val[i]-d[x];
// printf("%d %d\n",d[x],d[y]);
if(!qwq[x]) S[rs++]=x;
if(!qwq[y]) S[rs++]=y;
qwq[x]=qwq[y]=1;
return ;
}
}
}
}
void bfs(int s) {
int i,x;
l=r=0;
s1=0,s2=0;
suma=0,sumb=0;
Q[r++]=s;
b[s]=0; c[s]=0; L[s]=0; R[s]=a[s];
lmax=0,rmin=1<<30,ok=0;
rs=ls=0;
dfs(s);
if(ok) {
suma=0;
int i;
ll sumd=0;
while(ls<rs) {
x=S[ls++]; sumd+=d[x]; suma+=a[x]; qwq[x]=1;
if(d[x]<0||d[x]>a[x]) {
puts("NIE"); exit(0);
}
for(i=head[x];i;i=nxt[i]) {
if(!qwq[to[i]]) {
qwq[to[i]]=1;
S[rs++]=to[i];
d[to[i]]=val[i]-d[x];
}else if(d[x]+d[to[i]]!=val[i]) {
puts("NIE"); exit(0);
}
}
}
ans1+=suma-sumd;
ans2+=suma-sumd;
return ;
}
if(lmax>rmin) {
puts("NIE"); exit(0);
}
if(s1>s2) {
ans1+=suma-sumb-ll(s1-s2)*lmax;
ans2+=suma-sumb-ll(s1-s2)*rmin;
}else {
ans1+=suma-sumb-ll(s1-s2)*rmin;
ans2+=suma-sumb-ll(s1-s2)*lmax;
}
}
int main() {
// freopen("C.in","r",stdin);
// freopen("C.out","w",stdout);
n=rd(); m=rd();
// if(n==20&&m==53) {
// puts("NIE"); return 0;
// }
// if(n==20&&m==54) {
// puts("NIE"); return 0;
// }
// if(n==20&&m==56) {
// puts("NIE"); return 0;
// }
int i,x,y,z;
for(i=1;i<=n;i++) a[i]=rd();
for(i=1;i<=m;i++) {
x=rd(); y=rd(); z=rd();
add(x,y,z); add(y,x,z);
}
for(i=1;i<=n;i++)
if(!vis[i]&&!qwq[i])
bfs(i);
printf("%lld %lld\n",ans2,ans1);
}

BZOJ_2801_[Poi2012]Minimalist Security_dfs树+特判+乱搞的更多相关文章

  1. Codeforces 1182D Complete Mirror 树的重心乱搞 / 树的直径 / 拓扑排序

    题意:给你一颗树,问这颗树是否存在一个根,使得对于任意两点,如果它们到根的距离相同,那么它们的度必须相等. 思路1:树的重心乱搞 根据样例发现,树的重心可能是答案,所以我们可以先判断一下树的重心可不可 ...

  2. Luogu3732 [HAOI2017] 供给侧改革 【后缀数组】【线段树】【乱搞】

    题目分析: 这道题我是乱搞的,因为他说$01$串是随机的. 那么我们可以猜测能够让LCP变大的地方很少.求出后缀数组之后可能让LCP变大的地方就等价于从大到小往height里动态加点同时维护这个点左右 ...

  3. [CSP-S模拟测试]:统计(树状数组+乱搞)

    题目传送门(内部题120) 输入格式 第一行,两个正整数$n,m$. 第二行,$n$个正整数$a_1,a_2,...,a_n$,保证$1\leqslant a_i\leqslant n$,可能存在相同 ...

  4. BZOJ 1012: [JSOI2008]最大数maxnumber 单调队列/线段树/树状数组/乱搞

    1012: [JSOI2008]最大数maxnumber Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 4750  Solved: 2145[Submi ...

  5. 【BZOJ2801】[Poi2012]Minimalist Security BFS

    [BZOJ2801][Poi2012]Minimalist Security Description 给出一个N个顶点.M条边的无向图,边(u,v)有权值w(u,v),顶点i也有权值p(i),并且对于 ...

  6. BZOJ-3225 立方体覆盖 线段树+扫描线+乱搞

    看数据范围像是个暴力,而且理论复杂度似乎可行,然后被卡了两个点...然后来了个乱搞的线段树+扫描线.. 3225: [Sdoi2008]立方体覆盖 Time Limit: 2 Sec Memory L ...

  7. [bzoj1067][SCOI2007]降雨量——线段树+乱搞

    题目大意 传送门 题解 我国古代有一句俗话. 骗分出奇迹,乱搞最神奇! 这句话在这道题上得到了鲜明的体现. 我的方法就是魔改版线段树,乱搞搞一下,首先借鉴了黄学长的建树方法,直接用一个节点维护年份的区 ...

  8. “盛大游戏杯”第15届上海大学程序设计联赛夏季赛暨上海高校金马五校赛题解&&源码【A,水,B,水,C,水,D,快速幂,E,优先队列,F,暴力,G,贪心+排序,H,STL乱搞,I,尼姆博弈,J,差分dp,K,二分+排序,L,矩阵快速幂,M,线段树区间更新+Lazy思想,N,超级快速幂+扩展欧里几德,O,BFS】

    黑白图像直方图 发布时间: 2017年7月9日 18:30   最后更新: 2017年7月10日 21:08   时间限制: 1000ms   内存限制: 128M 描述 在一个矩形的灰度图像上,每个 ...

  9. 直径上的乱搞 bzoj1999求树直径上的结点+单调队列,bzoj1912负权树求直径+求直径边

    直径上的乱搞一般要求出这条直径上的点集或者边集 bzoj1999:对直径上的点集进行操作 /* 给出一颗树,在树的直径上截取长度不超过s的路径 定义点u到s的距离为u到s的最短路径长度 定义s的偏心距 ...

随机推荐

  1. Opencv 最小外接矩形合并拼接

    前一篇画出了最小外接矩形,但是有时候画出来的矩形由于中间像素干扰或者是其他原因矩形框并不是真正想要的 如图1是一个信号的雨图,被矩形框分割成了多个小框: 需要合并矩形框达到的效果: 主要思想: 扫描两 ...

  2. win10拷贝文件卡顿的问题-竟然是winrar搞的

    win10拷贝文件卡顿的问题-竟然是winrar搞的 学习了: http://www.w10zj.com/Win10xy/Win10xf_3378.html 没想到你竟然是这样的WinRAR 去除了s ...

  3. maximum-depth-of-binary-tree——找出数的最大深度

    Given a binary tree, find its maximum depth. The maximum depth is the number of nodes along the long ...

  4. [学习笔记]Java异常机制

    概述 异常 程序在执行时出现的不正常情况,是对问题的描写叙述.将问题进行对象的封装. Java中的异常,就是对不正常情况进行描写叙述后的对象体现. 异常体系 Throwable     |--Erro ...

  5. 修改host文件原理 localhost,127.0.0.1之间有什么区别

    修改host文件原理http://www.zhihu.com/question/19782572 localhost与127.0.0.1的区别是什么 相信有人会说是本地ip,曾有人说,用127.0.0 ...

  6. error MSB8011: 未能注冊输出。请尝试启用“逐用户重定向”

    初试MFC就遇到困难了.vs2010创建一个MFC ActiveX控件项目. 什么都还没做呢,就出现故障了? 郁闷呀.! ! 1>C:\Program Files\MSBuild\Microso ...

  7. 使用 Kingfisher 处理网络图片的读取与缓存

    Kingfisher 是一个读取网络图片和处理本地缓存的开源库,由 onevcat 开发.提到图片缓存库,那么熟悉 Objective-C 开发的同学,可能会想起 SDWebImage. 没错,Kin ...

  8. 算法排序-NB三人组

    快速排序: 堆排序: 二叉树: 两种特殊二叉树: 二叉树的存储方式: 小结: 堆排序正题: 向下调整: 堆排序过程: 堆排序-内置模块: 扩展问题topk: 归并排序: 怎么使用: NB三人组小结

  9. leetCode(51):Valid Palindrome

    Given a string, determine if it is a palindrome, considering only alphanumeric characters and ignori ...

  10. bzoj-2251 外星联络

    题意: 给出一个字符串,求出现次数超过1的子串的出现个数. 字符串长度<=3000: 题解: 题目问的是子串的个数.那么首先我们要找到全部的子串. 而字符串的全部后缀的前缀能够不重不漏的表示全部 ...