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]所罗门的宝藏
大概是最后一篇题解,其实只是想颓废一下打个故事 据古代传说记载,所罗门王即是智慧的代表,又是财富的象征.他建立了强大而富有的国家,聚集了大批的黄金象牙和钻石,并把这些价值连城的珍宝藏在一个神秘的地方, ...
随机推荐
- codeforces 792D - Paths in a Complete Binary Tree
#include<cstdio> #include<iostream> #define lowbit(x) x&(-x) typedef long long ll; u ...
- Oracle备份恢复之rman备份oracle数据库
备份需求和rman备份 oracle数据库的备份相关问答: 1)备份时数据库处于何种状态? 备份时数据库处于OPEN状态,这样数据库可以正常工作. 2)备份的数据备份在什么地方? 备份在本地磁盘. 3 ...
- N-N
---情景--- 关系:角色N-N区域 基础表:角色表.区域表 关系表:主键-角色id-区域id集 ---需求--- 实现“单个区域勾选角色”且不借助与非SQL脚本(php etc)遍历 ---疑惑- ...
- java cocurrent ConcurrentHashMap、读写锁、Condition、线程池、Barrier、CountDownLatch、Callable、BlockingQueue
Java并发学习笔记 - yang_net - 博客频道 - CSDN.NET Java并发学习笔记 - yang_net - 博客频道 - CSDN.NET 并发小结:高 ...
- CentOs7 安装最新版的Git
最近打算研究下Git并投入是用,当然要从安装开始了. 服务器的系统是CenterOs7,这个系统和之前的版本还些使用的不同,慢慢习惯吧. 安装方法有两种: 一.yum命令安装,此方法简单,并且会自动安 ...
- 解决下载的CHM文件无法显示网页问题
问题症状:打开CHM文件,左边目录齐全,可右边边框里却是无法显示网页. 解决方法:方法一:修改注册表1)新建一个文本文件2)添加如下内容:REGEDIT4[HKEY_LOCAL_MACHINE\SOF ...
- .NET基于分页控件实现真分页功能
下面利用分页控件实现分页功能.分页控件下载网址:http://www.webdiyer.com/ 从该网址下载AspNetPager.dll后,在VS2008中在工具箱中,右键 —> 选择项 — ...
- 【剑指offer】调整数组顺序使奇数位于偶数前面
一.题目: 输入一个整数数组,实现一个函数来调整该数组中数字的顺序,使得所有的奇数位于数组的前半部分,所有的偶数位于位于数组的后半部分,并保证奇数和奇数,偶数和偶数之间的相对位置不变. 二.思路: 用 ...
- PAT 1072 Gas Station[图论][难]
1072 Gas Station (30)(30 分) A gas station has to be built at such a location that the minimum distan ...
- ubuntu vim python配置
参考https://www.cnblogs.com/cjy15639731813/p/5886158.html 但是后面打开文件的时候会报错,参考https://blog.csdn.net/jeff_ ...