LG-P3552 [POI2013]SPA-Walk 题解
LG-P3552 [POI2013]SPA-Walk Solution
更好的阅读体验戳此进入
(建议您从上方链接进入我的个人网站查看此 Blog,在 Luogu 中图片会被墙掉,部分 Markdown 也会失效)
题面
存在
能到达输出 TAK
,反之输出 NIE
。
输入格式
n k
S T
(偷个懒就不写文字叙述了。。。)
Solution
这道题我本来还以为是和 LG-P7966 [COCI2021-2022#2] Hiperkocka 差不多的题,该题题解,按照那道题的思路想了一下然后假了,改了一下之后 T 掉了,寄,和之前的题关系不是很大,只是定义一样。
Lemma 1:对于一个
证明:A proof is left to the reader.
证明:这东西大多数地方都没有人证明,甚至官方题解,感觉可以当成一个已知结论记住,关于严谨证明网上也找到了个大佬的证明(看不懂),戳此进入。
Lemma 2:对于一个
证明:假设我们现在有两个连通块,其点集分别为
于是只要有了 Lemma 2,我们就可以很容易想到,令出发点和终点分别为
于是我们分别从 unordered_set
记录其所在连通块有哪些点,如果从搜索过程中遇到另一个点了,则两者同在一个小连通块中,直接输出连通然后 exit
,如果连通块大小超过 return
。两者都搜完后如果两个连通块都超过
另外个人建议把二进制转成 long long
再存,否则还会存在一个 hash 的复杂度,虽然我感觉好像嗯搞也能过???
然后写位移的时候记得写成 1ll
。
这个的复杂度大概是 我不会。
A proof is left to the reader.
然后。。。Luogu 评测记录
unordered_set
寄了,cc_hash_table
寄的更多,经典被卡常,调了亿会怎么 Luogu 上都是两个点 TLE,一个点 MLE,于是开始手搓 hash 挂链,队列之类的,最终终于在 Luogu 上把这破题给卡过去了。。。
Code
#define _USE_MATH_DEFINES
#include <bits/extc++.h>
#define PI M_PI
#define E M_E
#define npt nullptr
#define SON i->to
#define OPNEW void* operator new(size_t)
#define ROPNEW(arr) void* Edge::operator new(size_t){static Edge* P = arr; return P++;}
/******************************
abbr
uex => unexist
******************************/
using namespace std;
using namespace __gnu_pbds;
mt19937 rnd(random_device{}());
int rndd(int l, int r){return rnd() % (r - l + 1) + l;}
bool rnddd(int x){return rndd(1, 100) <= x;}
typedef unsigned int uint;
typedef unsigned long long unll;
typedef long long ll;
typedef long double ld;
template<typename T = int>
inline T read(void);
ll str2ll(char* s, int n){
ll ret(0), base(0);
for(int i = n - 1; i >= 0; --i)
ret += (1ll << (base++)) * (s[i] == '0' ? 0 : 1);
return ret;
}
#define MOD 2737321
struct Edge{
Edge* nxt;
ll val;
OPNEW;
}eData[4145149];
ROPNEW(eData);
Edge* head[2737330];
void clear(void){memset(head, 0, sizeof(head));}
void Add(ll val){
int idx = val % MOD;
head[idx] = new Edge{head[idx], val};
}
bool Check(ll val){
int idx = val % MOD;
for(auto i = head[idx]; i; i = i->nxt)
if(i->val == val)return true;
return false;
}
ll S, T;
int N, K;
ll cur[5100000];
int fnt(0), til(0);
void bfs(ll S, ll T){
fnt = til = 0;
cur[til++] = S;
Add(S);
while(fnt < til){
ll tp = cur[fnt++];
for(int base = 0; base <= N - 1; ++base){
ll val = tp ^ (1ll << base);
if(val == T)printf("TAK\n"), exit(0);
if(Check(val))continue;
else{
Add(val);
cur[til++] = val;
}
}
if(til > N * K)return;
}
printf("NIE\n"); exit(0);
}
char c[65];
vector < ll > values;
int main(){
// freopen("in.txt", "r", stdin);
N = read(), K = read();
scanf("%s", c); S = str2ll(c, N);
scanf("%s", c); T = str2ll(c, N);
if(S == T)printf("TAK\n"), exit(0);
for(int i = 1; i <= K; ++i){
scanf("%s", c); ll tmpp = str2ll(c, N);
values.push_back(tmpp);
}
for(auto i : values)Add(i);
bfs(S, T);
clear();
for(auto i : values)Add(i);
bfs(T, S);
printf("TAK\n");
fprintf(stderr, "Time: %.6lf\n", (double)clock() / CLOCKS_PER_SEC);
return 0;
}
template<typename T>
inline T read(void){
T ret(0);
short flag(1);
char c = getchar();
while(c != '-' && !isdigit(c))c = getchar();
if(c == '-')flag = -1, c = getchar();
while(isdigit(c)){
ret *= 10;
ret += int(c - '0');
c = getchar();
}
ret *= flag;
return ret;
}
UPD
update-2022_09_27 初稿
本文作者:Tsawke
本文链接:https://www.cnblogs.com/tsawke/p/16786788.html
版权声明:本作品采用知识共享署名-非商业性使用-禁止演绎 2.5 中国大陆许可协议进行许可。
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步