bzoj5470 / P4578 [FJOI2018]所罗门王的宝藏
错解:
设第$i$行上的值改变了$r1[i]$,第$j$列上的值改变了$r2[i]$
显然密码$(i,j,c)=r1[i]+r2[j]$
对于同一列上的两个密码$(i_{1},j,c_{1}),(i_{2},j,c_{2})$,它们的差值即为$c_{1}-c_{2}=r1[i_{1}]-r1[i_{2}]$
同一行上的同理。
这样我们就可以确定$r1[i],r2[j]$之间的关系,并以此判断
那么对于每组数据,我们可以$O(k^2)$两两枚举宝石,用上述方法判断即可。
同一个地方可能有两颗宝石
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cctype>
using namespace std;
void read(int &x){
char c=getchar();x=;bool f=;
while(!isdigit(c)) f=(f&&c!='-'),c=getchar();
while(isdigit(c)) x=(x<<)+(x<<)+(c^),c=getchar();
x=f?x:-x;
}
#define N 1005
int n,m,k,x[N],y[N],v[N],d1[N][N],d2[N][N];
bool w1[N][N],w2[N][N],ok;
int ask(int i,int j,int c){
if(c) return y[i]<y[j]?v[i]-v[j]:v[j]-v[i];
else return x[i]<x[j]?v[i]-v[j]:v[j]-v[i];
}
bool check(int i,int j){
if(x[i]==x[j]&&y[i]==y[j]&&v[i]!=v[j]) return ;//同个位置两颗宝石
if(y[i]==y[j]){
if(w1[x[i]][x[j]]&&d1[x[i]][x[j]]!=ask(i,j,)) return ;
d1[x[i]][x[j]]=d1[x[j]][x[i]]=ask(i,j,);
w1[x[i]][x[j]]=w1[x[j]][x[i]]=;
}
if(x[i]==x[j]){
if(w2[y[i]][y[j]]&&d2[y[i]][y[j]]!=ask(i,j,)) return ;
d2[y[i]][y[j]]=d2[y[j]][y[i]]=ask(i,j,);
w2[y[i]][y[j]]=w2[y[j]][y[i]]=;
}return ;
}
int main(){
int T;read(T);
while(T--){
memset(d1,,sizeof(d1));
memset(d2,,sizeof(d2));
memset(w1,,sizeof(w1));
memset(w2,,sizeof(w2));
read(n);read(m);read(k);ok=;
for(int i=;i<=k;++i)
read(x[i]),read(y[i]),read(v[i]);
for(int i=;i<=k&&ok;++i)
for(int j=i+;j<=k&&ok;++j)
ok=check(i,j);
printf(ok?"Yes\n":"No\n");
}return ;
}
上面这个做法被评论hack了
今天终于用差分约束过掉了
发现对于$(x1,y1,w1),(x2,y2,w2)$
如果$x1==x2$,那么可以得到$y1,y2$之间的操作差值$v[y1]-v[y2]=w1-w2$
于是通过这样在行和列分别建图
跑spfa判负环
记住多组数据,该清空的全清空掉
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
#define N 1005
#define M 2000005
int T,n,m,k,u[N],v[N],w[N],f1[N],f2[N];
bool vis1[N],vis2[N],ok; int Cnt1,hd1[N],nxt1[M],ed1[N],poi1[M],val1[M];
void adde1(int x,int y,int v){
nxt1[ed1[x]]=++Cnt1; hd1[x]=hd1[x]?hd1[x]:Cnt1;
ed1[x]=Cnt1; poi1[Cnt1]=y; val1[Cnt1]=v;
}
void link1(int x,int y,int v){adde1(x,y,v),adde1(y,x,-v);} int Cnt2,hd2[N],nxt2[M],ed2[N],poi2[M],val2[M];
void adde2(int x,int y,int v){
nxt2[ed2[x]]=++Cnt2; hd2[x]=hd2[x]?hd2[x]:Cnt2;
ed2[x]=Cnt2; poi2[Cnt2]=y; val2[Cnt2]=v;
}
void link2(int x,int y,int v){adde2(x,y,v),adde2(y,x,-v);} void spfa1(int x){
if(vis1[x]) ok=;
if(ok) return ;
vis1[x]=;
for(int i=hd1[x];i&&!ok;i=nxt1[i]){
int to=poi1[i];
if(f1[to]>f1[x]+val1[i])
f1[to]=f1[x]+val1[i],spfa1(to);
}
vis1[x]=;
}
void spfa2(int x){
if(vis2[x]) ok=;
if(ok) return ;
vis2[x]=;
for(int i=hd2[x];i&&!ok;i=nxt2[i]){
int to=poi2[i];
if(f2[to]>f2[x]+val2[i])
f2[to]=f2[x]+val2[i],spfa2(to);
}
vis2[x]=;
}
int main(){
scanf("%d",&T);
while(T--){
scanf("%d%d%d",&n,&m,&k);
f1[]=f2[]=ok=;
for(int i=;i<=n;++i) f1[i]=2e9;
for(int i=;i<=m;++i) f2[i]=2e9;
for(int i=;i<=n;++i) adde1(,i,);//虚拟源点建图,防止图不连通
for(int i=;i<=m;++i) adde2(,i,);
for(int i=;i<=k;++i){
scanf("%d%d%d",&u[i],&v[i],&w[i]);
for(int j=i-;j;--j){
if(v[i]==v[j]) link1(u[i],u[j],w[j]-w[i]);
if(u[i]==u[j]) link2(v[i],v[j],w[j]-w[i]);
}
}
spfa1(); spfa2();
puts(ok?"No":"Yes");
for(int i=;i<=n;++i) vis1[i]=hd1[i]=ed1[i]=;
for(int i=;i<=m;++i) vis2[i]=hd2[i]=ed2[i]=;
for(int i=;i<=Cnt1;++i) nxt1[i]=poi1[i]=;
for(int i=;i<=Cnt2;++i) nxt2[i]=poi2[i]=;
Cnt1=Cnt2=;
}return ;
}
bzoj5470 / P4578 [FJOI2018]所罗门王的宝藏的更多相关文章
- 【BZOJ5470】[FJOI2018]所罗门王的宝藏()
[BZOJ5470][FJOI2018]所罗门王的宝藏() 题面 BZOJ 洛谷 有\(n+m\)个变量,给定\(k\)组限制,每次告诉你\(a_i+b_j=c_k\),问是否有可行解. 题解 一道很 ...
- 洛谷P4578 [FJOI2018]所罗门王的宝藏(dfs)
题意 题目链接 Sol 对于每个询问\(x, y, c\) 从在\((x, y)\)之间连一条边权为\(c\)的双向边,然后就是解\(K\)个二元方程. 随便带个数进去找找环就行了 #include& ...
- P4578 [FJOI2018]所罗门王的宝藏
传送门 考虑一个位置答案传递性,如果某个位置的红宝石转动确定了,那么会引起连锁反应: 如图,绿色的转动确定了,那么那两个蓝色的转动也确定了 自己手玩一下,发现如果有解那么随便找一个开始然后一路玩下去最 ...
- 洛谷4578 & LOJ2520:[FJOI2018]所罗门王的宝藏——题解
https://www.luogu.org/problemnew/show/P4578 https://loj.ac/problem/2520 有点水的. 先转换成图论模型,即每个绿宝石,横坐标向纵坐 ...
- luoguP4578_ [FJOI2018]所罗门王的宝藏
题意 一个n*m的矩阵,初始值全为0,每一行每一列操作一次可以加1或者减1,问能否操作得到给定矩阵. 分析 行和列的分别的加减是可以相互抵消的,因此我们只需要考虑行的加和列的减. 对于给定矩阵每一个数 ...
- 题解【[FJOI2018]所罗门王的宝藏】
本题解同步于luogu emmm切了近年省选题来写题解啦qwq 该题较其他省选题较水吧(否则我再怎么做的出来 思路是图论做法,做法上楼上大佬已经讲的很清楚了,我来谈谈代码实现上的一些细节 \[\tex ...
- 【LOJ】 #2520. 「FJOI2018」所罗门王的宝藏
题解 发现似乎相当于问一个2000个元的方程组有没有解-- 然而我懵逼啊-- 发现当成图论,两个点之间连一条边,开始BFS,每个点的值赋成边权减另一个点的点权 如果一个环不合法那么肯定无解 代码 #i ...
- yyb省选前的一些计划
突然意识到有一些题目的计划,才可以减少大量查水表或者找题目的时间. 所以我决定这样子处理. 按照这个链接慢慢做. 当然不可能只做省选题了. 需要适时候夹杂一些其他的题目. 比如\(agc/arc/cf ...
- [FJOI2018]所罗门的宝藏
大概是最后一篇题解,其实只是想颓废一下打个故事 据古代传说记载,所罗门王即是智慧的代表,又是财富的象征.他建立了强大而富有的国家,聚集了大批的黄金象牙和钻石,并把这些价值连城的珍宝藏在一个神秘的地方, ...
随机推荐
- ABP之框架体系
一 .框架体系的介绍 ABP框架采用的是DDD(领域驱动设计)的原则,可以很方便实现项目之间的松耦合,采用模块化的方式,方便对框架的扩展. 按照DDD的原则,首先将项目分为四层: 展现层:用来展现给用 ...
- easyui datagrid 加载 历险记(dom中已经加载,fit:true 时改变浏览器大小是会显示出来)
(dom中已经加载,fit:true 时改变浏览器大小是会显示出来) 第一个想到的就是resize datagird 大小!可是没有用 ... 答案是加载的的div height为0导至的(//To ...
- C++中引用与取地址
所谓引用就是为对象起一个别名.例如变量b = &a,b就是a的一个引用.对b的任何操作等同于对a的操作,也就是说,如果你改变了b的值,同时a的值也会发生改变.b就是a的另外一个名字,他们实质是 ...
- WebWorker的浏览器"异步线程"
worker新线程: 1.通过postMessage( data ) 方法来向主线程发送数据; 2.绑定onmessage方法来接收主线程发送过来的数据: 3.worker外部文件不允许使用win ...
- 14nm或于6月量产,中芯首次披露12nm及第二代FinFET "N+1"计划(详细数据)
日前中芯国际公布2018年度第四季度业绩,实现营收7.88亿美元,14nm工艺进入客户验证阶段,可望于今年6月份量产,且12nm工艺开发取得突破. 根据中芯国际披露的财报,2018年第四季度实现营业收 ...
- python 全局变量引用与修改
一.引用 使用到的全局变量只是作为引用,不在函数中修改它的值的话,不需要加global关键字.如: #! /usr/bin/python a = 1 b = [2, 3] def func(): if ...
- Hibernate错误
1.Field 'id' doesn't have a default value 原来是我的数据设计的时候,把主键的类型定义为int的,原本想是用自增的方式来的,可是由于自己的粗心,写sql语句的时 ...
- zabbix 报错汇总
打开zabbix web界面点击profile出现以下报错信息: scandir() has been disabled for security reasons [profile.php:198 → ...
- android studio常用控件
1.Button设置不同的样式 <?xml version="1.0" encoding="utf-8"?> <selector xmlns: ...
- 【剑指offer】替换空格
一.题目: 请实现一个函数,将一个字符串中的空格替换成“%20”.例如,当字符串为We Are Happy.则经过替换之后的字符串为We%20Are%20Happy. 二.思路: Python代码,先 ...