noi.ac NA537 【Graph】
本来以为过了...然后FST了...
吐槽:nmdGraph为什么不连通...
这题想法其实非常\(na\ddot{\imath}ve\),就是对于一个连通块先钦点一个点为根,颜色是\(1\),考虑到边权限制点权,可以做二分图染色,钦点连通块内的某个形如树形的边的子集是全部合法的,显然一棵树是一定有解的,对于此时的\(\min ,\max\)只需要看根节点的取值范围取\(\min ,\max\),对于图的话显然就是多了一些边,判断多的边两端节点是否同色,如果同色则意味着根节点的权值是唯一确定的,如果不是整数则无解,否则直接赋值重跑一遍计算\(ans\)即可,复杂度\(\mathcal{O}(n+m)\)。
因为代码是从FST的改过来的,memset
其实会T,但是懒得改了,所以下面代码复杂度是假的,不过不影响正确性
#include<bits/stdc++.h>
#define yes printf("%lld %lld\n",ansa,ansb);exit(0)
#define no printf("NIE\n");exit(0)
#define int long long
using namespace std;
signed ch;
void qread(int &xx){
xx=0;ch=getchar();
while(!isdigit(ch)){
ch=getchar();
}
while(isdigit(ch)){
xx=xx*10+ch-'0';
ch=getchar();
}
}
const int N=5e5+5,M=6e6+6;
int n,m,ans,ansa,ansb,p[N],vis[N];
int fir[N],nxt[M],to[M],edge[M],cntedge,col[N],c[N],cnt[3];
int mi[3]={0,0,0x3f3f3f3f},up[3]={0,0,0x3f3f3f3f};
void addedge(int u,int v,int w){
++cntedge;to[cntedge]=v;edge[cntedge]=w;nxt[cntedge]=fir[u];fir[u]=cntedge;
}
namespace subtree{
queue<int>q;
void bfs(int u){
for(int now=fir[u],v;now;now=nxt[now]){
v=to[now];
if(col[v]){
continue;
}
c[v]=edge[now]-c[u];
col[v]=3-col[u];
++cnt[col[v]];
ans+=c[v];
mi[col[v]]=min(mi[col[v]],c[v]);
up[col[v]]=min(up[col[v]],p[v]-c[v]);
q.push(v);
}
}
void solve(){
q.push(1);col[1]=1;++cnt[1];up[1]=p[1];
while(!q.empty()){
int u=q.front();q.pop();
bfs(u);
}
if(up[1]+up[2]<0){
no;
}
if(up[1]<0){
for(int i=1;i<=n;i++){
col[i]==1?(c[i]+=up[1],ans+=up[1]):(c[i]-=up[1],ans-=up[1]);
}
up[2]+=up[1];mi[2]-=up[1];mi[1]+=up[1];up[1]=0;
}
if(up[2]<0){
for(int i=1;i<=n;i++){
col[i]==2?(c[i]+=up[2],ans+=up[2]):(c[i]-=up[2],ans-=up[2]);
}
up[1]+=up[2];mi[1]-=up[2];mi[2]+=up[2];up[2]=0;
}
if(mi[1]+up[2]<0||mi[2]+up[1]<0||mi[1]+mi[2]<0){
no;
}
if(mi[1]<0){
for(int i=1;i<=n;i++){
col[i]==1?c[i]-=mi[1],ans-=mi[1]:c[i]+=mi[1],ans+=mi[1];
}
up[2]+=mi[1];mi[2]+=mi[1];up[1]+=mi[1];mi[1]=0;
}
else if(mi[2]<0){
for(int i=1;i<=n;i++){
col[i]==2?c[i]-=mi[2],ans-=mi[2]:c[i]+=mi[2],ans+=mi[2];
}
up[1]+=mi[2];mi[1]+=mi[2];up[2]+=mi[2];mi[2]=0;
}
if(cnt[1]==cnt[2]){
ansa=ansb=ans;
}
else if(cnt[1]<cnt[2]){
ansa=ans-min(mi[2],up[1])*(cnt[2]-cnt[1]);
ansb=ans+min(mi[1],up[2])*(cnt[2]-cnt[1]);
}
else{
ansa=ans-min(mi[1],up[2])*(cnt[1]-cnt[2]);
ansb=ans+min(mi[2],up[1])*(cnt[1]-cnt[2]);
}
yes;
}
}
namespace qwq{
queue<int>q;
int s,id=0;bool flag;
bool check(){
while(!q.empty()){
q.pop();
}
memset(col,0,sizeof col);
q.push(s);col[s]=1;ans=c[s];
while(!q.empty()){
int u=q.front();q.pop();
vis[u]=id;
if(c[u]<0||c[u]>p[u]){
no;
}
for(int now=fir[u],v;now;now=nxt[now]){
v=to[now];
if(col[v]){
if(c[u]+c[v]!=edge[now]){
no;
}
continue;
}
c[v]=edge[now]-c[u];
col[v]=3-col[u];
ans+=c[v];
q.push(v);
}
}
ansa+=ans;ansb+=ans;
return 1;
}
void bfs(int u){
vis[u]=id;
for(int now=fir[u],v;now;now=nxt[now]){
v=to[now];
if(col[v]){
if(col[u]^col[v]){
if(c[u]+c[v]!=edge[now]){
no;
}
}
else{
if(((c[u]+c[v])&1)^(edge[now]&1)){
no;
}
if(col[u]^2){
c[s]=(edge[now]-c[u]-c[v])>>1;
if(check()){
flag=1;return;
}
else{
no;
}
}
else{
c[s]=(c[u]+c[v]-edge[now])>>1;
if(check()){
flag=1;return;
}
else{
no;
}
}
}
continue;
}
c[v]=edge[now]-c[u];
col[v]=3-col[u];
++cnt[col[v]];
ans+=c[v];
mi[col[v]]=min(mi[col[v]],c[v]);
up[col[v]]=min(up[col[v]],p[v]-c[v]);
q.push(v);
}
}
void work(){
while(!q.empty()){
q.pop();
}
flag=0;
memset(cnt,0,sizeof cnt);
up[2]=mi[2]=0x3f3f3f3f;mi[1]=0;
q.push(s);col[s]=1;++cnt[1];up[1]=p[s];ans=0;
while(!q.empty()){
int u=q.front();q.pop();bfs(u);
}
if(flag){
return;
}
if(up[1]+up[2]<0){
no;
}
if(up[1]<0){
for(int i=1;i<=n;i++){
if(vis[i]!=id){
continue;
}
col[i]==1?(c[i]+=up[1],ans+=up[1]):(c[i]-=up[1],ans-=up[1]);
}
up[2]+=up[1];mi[2]-=up[1];mi[1]+=up[1];up[1]=0;
}
if(up[2]<0){
for(int i=1;i<=n;i++){
if(vis[i]!=id){
continue;
}
col[i]==2?(c[i]+=up[2],ans+=up[2]):(c[i]-=up[2],ans-=up[2]);
}
up[1]+=up[2];mi[1]-=up[2];mi[2]+=up[2];up[2]=0;
}
if(mi[1]+up[2]<0||mi[2]+up[1]<0||mi[1]+mi[2]<0){
no;
}
if(mi[1]<0){
for(int i=1;i<=n;i++){
if(vis[i]!=id){
continue;
}
col[i]==1?c[i]-=mi[1],ans-=mi[1]:c[i]+=mi[1],ans+=mi[1];
}
up[2]+=mi[1];mi[2]+=mi[1];up[1]+=mi[1];mi[1]=0;
}
else if(mi[2]<0){
for(int i=1;i<=n;i++){
if(vis[i]!=id){
continue;
}
col[i]==2?c[i]-=mi[2],ans-=mi[2]:c[i]+=mi[2],ans+=mi[2];
}
up[1]+=mi[2];mi[1]+=mi[2];up[2]+=mi[2];mi[2]=0;
}
if(cnt[1]==cnt[2]){
ansa+=ans;ansb+=ans;
}
else if(cnt[1]<cnt[2]){
ansa+=ans-min(mi[2],up[1])*(cnt[2]-cnt[1]);
ansb+=ans+min(mi[1],up[2])*(cnt[2]-cnt[1]);
}
else{
ansa+=ans-min(mi[1],up[2])*(cnt[1]-cnt[2]);
ansb+=ans+min(mi[2],up[1])*(cnt[1]-cnt[2]);
}
}
void solve(){
for(int i=1;i<=n;i++){
if(!vis[i]){
++id;s=i;
work();
}
}
yes;
}
}
signed main(){
qread(n);qread(m);
for(int i=1;i<=n;i++){
qread(p[i]);
}
for(int i=1,u,v,w;i<=m;i++){
qread(u);qread(v);qread(w);addedge(u,v,p[u]+p[v]-w);addedge(v,u,p[u]+p[v]-w);
}
if(n==m+1){
subtree::solve();
}
else{
qwq::solve();
}
no;
return 0;
}
noi.ac NA537 【Graph】的更多相关文章
- noi.ac NA536 【打地鼠】
又一道可写的小清新思维题 其实想到倒着做了,然而还是因为T1害人不浅(我太菜了),所以并没有写 考虑两个局面不同,显然至少打了一次地鼠,基于操作的颜色覆盖性质,我们可以考虑把操作倒着做,对于一个X点, ...
- noi.ac NA535 【生成树】
因为太蠢一直写T1也没仔细想,赛后发现是个真小清新思维题,本质构造??? 首先显然不会无解,这个随随便便证一下就有了 另外给的式子没啥意义,也就能说明颜色随机???害人不浅 然后就从\(1\)开始,钦 ...
- noi.ac NA534 【猫】
一眼暴力DP 再一眼决策单调性? 打个表以为是四边形不等式?? 最后发现是斜率优化??? 于是成功写了个假斜率优化真四边形不等式拿了\(80\) 设\(f[i][j]\)表示有\(i\)个工作人员出发 ...
- NOI.AC#2007-light【根号分治】
正题 题目链接:http://noi.ac/problem/2007 题目大意 \(n\)个格子排成一排,每个格子有一个\(0/1\)和一个颜色.开始每个格子都是\(0\),\(q\)次操作取反一个颜 ...
- NOI.AC#2266-Bacteria【根号分治,倍增】
正题 题目链接:http://noi.ac/problem/2266 题目大意 给出\(n\)个点的一棵树,有一些边上有中转站(边长度为\(2\),中间有一个中转站),否则就是边长为\(1\). \( ...
- AC日记——【模板】Link Cut Tree 洛谷 P3690
[模板]Link Cut Tree 思路: LCT模板: 代码: #include <bits/stdc++.h> using namespace std; #define maxn 30 ...
- AC日记——【模板】点分治(聪聪可可) 洛谷 P2634
[模板]点分治(聪聪可可) 思路: 点分治: (感谢灯神) 代码: #include <bits/stdc++.h> using namespace std; #define maxn 2 ...
- AC日记——【模板】分块/带修改莫队(数颜色) 洛谷 P1903
[模板]分块/带修改莫队(数颜色) 思路: 带修改莫队: (伏地膜xxy): 代码: #include <bits/stdc++.h> using namespace std; #defi ...
- AC日记——【模板】普通平衡树(Treap/SBT) 洛谷 P3369
[模板]普通平衡树(Treap/SBT) 思路: 劳资敲了一个多星期: 劳资终于a了: 劳资一直不a是因为一个小错误: 劳资最后看的模板: 劳资现在很愤怒: 劳资不想谈思路!!! 来,上代码: #in ...
随机推荐
- JavaScript参考DOM部分
目录 DOM完整版 DOM 介绍 节点 节点树 Node接口 属性 方法 NodeList 接口,HTMLCollection 接口 介绍 NodeList.prototype.length Node ...
- golang struct结构体初始化的几种方式
type User struct { Id int `json:"id" orm:"auto"` // 用户名 Username string `json:&q ...
- PJzhang:网络数据单位小比特
猫宁!!! 参考链接:https://blog.csdn.net/qq_38880380/article/details/79887704 https://www.cnblogs.com/Flycho ...
- 【AMAD】beaker -- 用于session和缓存的WSGI中间件
简介 动机 作用 个人评分 简介 Beaker1是一个web session和通用缓存库,并且包含一个WSGI中间件可以用于你的web应用. 动机 Beaker是基于MyghtyUtils2(一个古老 ...
- sql注入知识点整理(基础版)
sql注入知识点整理(基础版) 基本步骤 判断是否报错 判断闭合符号 判断注入类型 构建payload 手工注入或者编写脚本 基本注入类型 报错型注入 floor公式(结果多出一个1):and (se ...
- Jenkins中shell-script执行报错sh: line 2: npm: command not found
<1>本地执行npm run build--正常 <2>查看环境变量--正常 [root@localhost bin]# echo $PATH /usr/local/node/ ...
- 针对yarn的8088端口攻击
参考: https://www.wangbokun.com/%E8%BF%90%E7%BB%B4/2019/09/02/%E6%8C%96%E7%9F%BF%E7%97%85%E6%AF%92.htm ...
- 3.Java和hadoop的安装
先创建目录 [hadoop@node1 opt]$ cd /opt [hadoop@node1 opt]$ sudo mkdir /opt/softwares [hadoop@node1 opt]$ ...
- Windows 2016 安装单机版本Oracle ASM 的简单说明
发现这样弄完 启动之后 就挂了 真蛋疼. 改天再研究一下. 1. 需要给磁盘处理一下 建议使用压缩卷的模式进行处理 如图示 需要新建简单卷 注意设置 然后不进行格式化 2. 然后安装oracle的g ...
- Kick Start 2019 Round B Energy Stones
对我很有启发的一道题. 这道题的解法中最有思维难度的 observation 是 For simplicity, we will assume that we never eat a stone wi ...