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 ...
随机推荐
- 怎么在 localhost 下访问多个 Laravel 项目,通过一个IP访问多个项目(不仅仅是改变端口哦)
server { listen 80; server_name blog.sweetsunnyflower.com; index index.html index.htm index.php; cha ...
- Qt qss 动态属性-不同条件不同显示
一. 1.为了用户界面外观的动态变化,属性选择器可以与动态属性组合使用. 2.当一个属性值变化时,所引用的样式不会自动更新.相反地,必须手动触发更新才会生效.unpolish()用于清理之前的样式,而 ...
- 【.NET】ASP.Net IE10+ SCRIPT:XXX_doPostBack 未定义
问题描述 GridView中分页控件,点击分页无反应,Linkbutton点击无反应,打开Web控制台,发现如下错误:SCRIPTXXX:_doPostBack 未定义:查询后得知,是由于.NET F ...
- 【MapReduce】一、MapReduce简介与实例
(一)MapReduce介绍 1.MapReduce简介 MapReduce是Hadoop生态系统的一个重要组成部分,与分布式文件系统HDFS.分布式数据库HBase一起合称为传统Hadoop的三 ...
- 一加手机刷入第三方Rec
首先阐述一下刷机的整体流程: 备份数据(可选):短信.联系人.通话记录.图片.应用数据的云端同步. 解锁 刷入第三方Recovery(简称Rec). 进入第三方Rec,刷第三方ROM. 刷机成功 解锁 ...
- hbase的hue部署和使用
1.组件版本信息 zookeeper hadoop hbase hue zookeeper-3.4.12 hadoop-3.0.3 hbase-2.1.5 4.4.0 2. ...
- C# while循环及for循环,for循环的嵌套,冒泡循环
循环四要素:初始条件.循环条件.循环体.状态改变 初始条件:开始进入循环 所需要的 第一次条件 循环条件:执行循环所需要满足的条件 循环体:每次循环要执行的代码 状态改变:执行完当前循环体后 循环条件 ...
- 【有奖征集】报表模板库邀您提反馈,轻松赢取P30!
>>立即参赛 赛事初衷 大数据时代,数据的价值愈发彰显,什么样的报表才能真正帮助业务决策?这几乎是所有信息化建设的企业和个人都在思考的问题. 作为报表领域标杆企业,葡萄城于2017年推出了 ...
- SQL的循环嵌套算法:NLP算法和BNLP算法
MySQL的JOIN(二):JOIN原理 表连接算法 Nested Loop Join(NLJ)算法: 首先介绍一种基础算法:NLJ,嵌套循环算法.循环外层是驱动表,循坏内层是被驱动表.驱动表会驱动被 ...
- AssertionError [ERR_ASSERTION]: Task function must be specified,gulp版本不一致
报错信息: vue项目打包报错 > innovate-admin-vue@ build /home/soldier/SOLDIER/IDE_project/webStorm_project/in ...