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 ...
随机推荐
- Day04:集合框架(下) / 集合操作——线性表(一)
对象转型 向上转型: 什么是向上造型? 子类对象赋给父类引用 父类引用指向子类对象 父类类型 引用=子类对象; 子类转成父类 默认进行(父类引用指用子类对象). 为什么需要向上造型? 子类对象可 ...
- office web apps安装部署,配置https,负载均衡(六)配置负载均衡
owa可以采用任何的负载均衡方案,我们这里采用阿里云提供的负载均衡解决方案 前提条件,你已经配置了一台域控制器,两台域服务器[即安装了owa相关软件,并将计算机隶属于域]: 如果您不清楚怎么做,那么请 ...
- Vi或者Vim下按了ctrl+s后终端卡住了咋办?
在Vi或者Vim下按了ctrl+s后终端卡住了咋办? 习惯了在windows下写程序,也习惯了按ctrl+s 保存代码. 在用vim的时候,也习惯性的按ctrl+s结果就是如同终端死掉了一样. 原因: ...
- 【神经网络与深度学习】【C/C++】ZLIB学习2
Zlib文件压缩和解压 开源代码:http://www.zlib.net/ zlib使用手册:http://www.zlib.net/manual.html zlib wince版:http://ww ...
- XXE漏洞简析
0x00.什么是XXE? XML外部实体注入(XML External Entity Injection) XML基础 XML用于标记电子文件使其具有结构性的标记语言,可以用来标记数据.定义数据类型. ...
- 从零开始,SpreadJS 新人学习笔记
Hello,大家好,我是Fiona,从事前端开发工作,我十分热爱我的工作和一直默默栽培我的老板(这段请加粗). 前不久,接到老板的安排: 说实话,接到这个需求,我整个人的状态是这样的: 但是,我不能辜 ...
- 批量删除Maven本地仓库中未下载完成的jar包(不完整的jar包)
1.删除repository库目录下所有后缀名是.lastUpdated的文件 2.进入maven本地仓库地址: CMD进入windows的路径(或在仓库目录的地址栏直接输入CMD,回车自动打开); ...
- HTML页面左上角图标
显示网页左上角标志图标 <link rel="shortcut icon"type="image/x-icon"href="images/fav ...
- The Digits String
https://ac.nowcoder.com/acm/contest/338/L 题解: 当n==1时,0-9填上的话,对4取余,分别是余数为0的3个,1的3个,2的2个,3的2个: 当n==2时, ...
- leecode100热题 HOT 100(2)
# 题名 题解 通过率 难度 出现频率 142 环形链表 II 43.3% 中等 146 LRU缓存机制 43.3% 中等 148 排序链表 ...