传送门

考场上写的记忆化不够快……和暴力一个分

  • 如果题面里有提到类似「从点1出发」的字样,特别注意点1根本就没有连边的情况

这题写记忆化的时候是想搜出所有可能的组合,

那么对于一个点u,剩余深度为d时的可能后缀数是一定的,可以记录下来

那就开个vector记一下,访问完子节点可以sort+unique去重,于是T飞

然后首先有个小优化:

可以不试着组合前后缀枚举能构成的结果

注意到 \(d \leqslant 20\) ,还可以枚举结果状态,每次跑个check就可以了

这个后缀的记忆化优化就很有用了

而且会有不少重边什么的,可以先去重

然而然后还是会T一个点

正解用meet in middle优化了下dfs

这样每个点要记的情况从\(2^{20}\)变成\(2^{10}\),就开得下数组了

而且dfs也能快巨多

  • 所以需要爆搜某些特定组合/边权和/异或和(?)的时候可以考虑meet in middle优化下

Code:

#include <bits/stdc++.h>
using namespace std;
#define INF 0x3f3f3f3f
#define N 150
#define ll long long
#define ld long double
#define usd unsigned
#define ull unsigned long long
//#define int long long #define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf, 1, 1<<21, stdin)), p1==p2?EOF:*p1++)
char buf[1<<21], *p1=buf, *p2=buf;
inline int read() {
int ans=0, f=1; char c=getchar();
while (!isdigit(c)) {if (c=='-') f=-f; c=getchar();}
while (isdigit(c)) {ans=(ans<<3)+(ans<<1)+(c^48); c=getchar();}
return ans*f;
} int n, m, d, D;
int head[N], size;
int dis0[N][N], dis1[N][N];
bool edge0[105], edge1[105];
struct edge{int to, next, val;}e[100010];
inline void add(int s, int t, int w) {edge* k=&e[++size]; k->to=t; k->val=w; k->next=head[s]; head[s]=size;} namespace force{
bool vis[1<<21];
void dfs(int u, int s, int d) {
//cout<<"dfs "<<u<<' '<<s<<' '<<d<<endl;
if (d<=0) {vis[s]=1; return ;}
for (int i=head[u]; i; i=e[i].next) {
dfs(e[i].to, (s<<1)|e[i].val, d-1);
}
}
void solve() {
dfs(1, 0, d);
int lim=1<<d, ans=0;
for (int i=0; i<lim; ++i) if (vis[i]) ++ans; //, cout<<i<<' '; cout<<endl;
printf("%d\n", ans);
exit(0);
}
} namespace task1{
bool vis[1<<21];
vector<int> vec[105][22];
void dfs(int u, int d) {
//if (clock()>800000) {cout<<(1<<D)<<endl; exit(0);}
//cout<<"dfs "<<u<<' '<<d<<endl;
//++cnt[u][d];
if (vec[u][d].size()) return ;
if (d<=1) {
bool t[2]={0, 0};
for (int i=head[u],v; i; i=e[i].next) {
if (!t[e[i].val]) vec[u][d].push_back(e[i].val), t[e[i].val]=1; //, cout<<1<<endl;
//cout<<i<<endl;
}
//cout<<"vec "<<u<<' '<<d<<": "; for (int i=0; i<vec[u][d].size(); ++i) cout<<vec[u][d][i]<<' '; cout<<endl;
return ;
}
for (int i=head[u],v; i; i=e[i].next) {
v = e[i].to;
dfs(v, d-1);
//cout<<"go "<<v<<' '<<d-1<<endl;
for (int j=0; j<vec[v][d-1].size(); ++j)
vec[u][d].push_back((e[i].val<<(d-1))|vec[v][d-1][j]); //, cout<<u<<' '<<d<<' '<<(e[i].val<<(d-1))<<' '<<vec[v][d-1][j]<<endl;
}
sort(vec[u][d].begin(), vec[u][d].end());
vector<int>::iterator it=unique(vec[u][d].begin(), vec[u][d].end());
while (it!=vec[u][d].end()) vec[u][d].pop_back();
//cout<<"vec "<<u<<' '<<d<<": "; for (int i=0; i<vec[u][d].size(); ++i) cout<<vec[u][d][i]<<' '; cout<<endl;
}
void solve() {
dfs(1, d);
//int lim=1<<n, ans=0;
//cout<<double(sizeof(cnt))/1024/1024<<endl;
//for (int i=0; i<lim; ++i) if (vis[i]) ++ans;
//cout<<3<<endl;
printf("%d\n", vec[1][d].size());
//cout<<vec[1][d].size()<<endl;
//for (int i=0; i<vec[1][d].size(); ++i) cout<<vec[1][d][i]<<' '; cout<<endl;
//for (int i=1; i<=n; ++i) {for (int j=1; j<=d; ++j) cout<<cnt[i][j]<<' '; cout<<endl;}
exit(0);
}
} namespace task2{
unordered_map<int, bool> mp[105][22];
int cnt=0;
bool dfs(int u, int d, int s) {
//++cnt;
//cout<<"dfs "<<u<<' '<<d<<' '<<bitset<5>(s)<<' '<<bitset<5>(s>>(d-1))<<endl;
if (d<=0) return 1;
if (mp[u][d].find(s)!=mp[u][d].end()) return mp[u][d][s];
if (s>>(d-1)) {if (!edge1[u]) return 0;}
else {if (!edge0[u]) return 0;}
for (int i=head[u],s1=s>>(d-1),s2=s&((1<<(d-1))-1); i; i=e[i].next)
if (e[i].val==s1 && dfs(e[i].to, d-1, s2)) {mp[u][d][s]=1; return 1;}
mp[u][d][s]=0;
return 0;
}
void solve() {
int lim=1<<d, ans=0;
for (int i=0; i<lim; ++i)
if (dfs(1, d, i)) ++ans;
printf("%d\n", ans);
//cout<<"cnt: "<<cnt<<endl;
exit(0);
}
} namespace task{
char mp[105][105][21][1<<11];
bool dfs(int u, int to, int d, int s) {
//cout<<"dfs "<<u<<' '<<to<<' '<<d<<' '<<s<<endl;
if (d<=0) return u==to;
if (mp[u][to][d][s]) return mp[u][to][d][s]>>1;
if (s>>(d-1)) {if (!edge1[u]) return 0;}
else {if (!edge0[u]) return 0;}
for (int i=head[u],s1=s>>(d-1),s2=s&((1<<(d-1))-1); i; i=e[i].next)
if (e[i].val==s1 && dfs(e[i].to, to, d-1, s2)) {mp[u][to][d][s]=3; return 1;}
mp[u][to][d][s]=1;
return 0;
}
void solve() {
int lim=1<<d, ans=0, l1=d/2, l2=d-d/2;
//cout<<"l: "<<l1<<' '<<l2<<endl;
for (int i=0; i<lim; ++i) {
for (int j=1; j<=n; ++j)
if (dfs(1, j, l1, i>>l2))
for (int k=1; k<=n; ++k)
if (dfs(j, k, l2, i&((1<<l2)-1))) {
++ans;
//cout<<"++ans: "<<i<<endl;
goto jump;
}
jump: ;
}
printf("%d\n", ans);
exit(0);
}
} signed main()
{
#ifdef DEBUG
freopen("1.in", "r", stdin);
#endif
bool all_zero=1, all_one=1; n=read(); m=read(); d=read(); D=d;
for (int i=1,u,v,c; i<=m; ++i) {
u=read(); v=read(); c=read();
//add(u, v, c); add(v, u, c);
if (c) dis1[u][v]=dis1[v][u]=1;
else dis0[u][v]=dis0[v][u]=1;
if (c) edge1[u]=edge1[v]=1;
else edge0[u]=edge0[v]=1;
if (c) all_zero=0;
else all_one=0;
}
for (int i=1; i<=n; ++i) for (int j=i; j<=n; ++j) if (dis1[i][j]) add(i, j, 1), add(j, i, 1);
for (int i=1; i<=n; ++i) for (int j=i; j<=n; ++j) if (dis0[i][j]) add(i, j, 0), add(j, i, 0);
if (!head[1]) {puts("0"); return 0;}
if (all_zero || all_one) {puts("1"); return 0;}
//if (d<=5) force::solve();
//else task1::solve();
task::solve(); return 0;
}

题解 y的更多相关文章

  1. 2018HN省队集训

    HNOI2018省队集训 Day 1 流水账 T1 tree 换根+求\(lca\)+求子树和,一脸bzoj3083遥远的国度的既视感.子树和讨论一下就好了,\(lca\)?也是大力讨论一波. 先写了 ...

  2. B-Quadratic equation_2019牛客暑期多校训练营(第九场)

    题意 解下列方程 \((x+y) \equiv b \ mod \ p\) \((x\ *\ y) \equiv c \ mod \ p\) 题解 \(y = b-x\) 带入二式 \(x * (b- ...

  3. Codeforces Round #549 (Div. 2) F 数形结合 + 凸包(新坑)

    https://codeforces.com/contest/1143/problem/F 题意 有n条形如\(y=x^2+bx+c\)的抛物线,问有多少条抛物线上方没有其他抛物线的交点 题解 \(y ...

  4. P5596 【XR-4】题 笔记

    P5596 [XR-4]题 其实这题我昨天没做出来--所以今天写一下笔记 昨天我还信誓旦旦地说这一定是一道黑题\(OTZ\).果然菜是原罪. 另外吐槽一下科技楼机房频繁停电,昨天写了两小时的树刨和倍增 ...

  5. 牛客网暑期ACM多校训练营(第二场)message

    传送门:https://ac.nowcoder.com/acm/problem/16631 题意 对于直线y=ax+b,给出n个的a[i]和b[i].m次询问,每次询问给出直线y=cx+d的c[i]和 ...

  6. ThinkPHP 汉字转成多种形式拼音

    模型: <?php namespace Admin\Model; use Think\Model; /** * 汉字转拼音 * @author huangguojin */ class ZHMo ...

  7. 「题解」:y

    问题 B: y 时间限制: 1 Sec  内存限制: 256 MB 题面 题面谢绝公开. 题解 考虑双向搜索. 定义$cal_{i,j,k}$表示当前已经搜索状态中是否存在长度为i,终点为j,搜索过边 ...

  8. 小Y的棋盘问题 题解

    有一个n*m的棋盘,上面有一些棋子,每行每列最多只会有一个棋子,不会有两个棋子八连通.问随机一个空格子作为起点,再随机地选择一个空格子作为终点,求问不经过任意棋子最短路的期望长度是多少.多组,n,m& ...

  9. POJ3243:Clever Y——题解

    http://poj.org/problem?id=3243 求最小的非负整数y满足x^y=k(mod z) 写完板子之后等待了半个小时poj才终于进入…… poj不行啊.jpg 以前一直觉得BSGS ...

随机推荐

  1. ARTS第三周

    第三周.上周欠下了 赶紧补上,糟糕了 还有第四篇也得加紧了 难受. 1.Algorithm:每周至少做一个 leetcode 的算法题2.Review:阅读并点评至少一篇英文技术文章3.Tip:学习至 ...

  2. 「BZOJ 2956」模积和

    「BZOJ 2956」模积和 令 \(l=\min(n,m)\).这个 \(i\neq j\) 非常不优雅,所以我们考虑分开计算,即: \[\begin{aligned} &\sum_{i=1 ...

  3. STP概述简介及生成树算法

    目录: STP概述 STP简介 生成树算法 选择根网桥 选择根端口 选择指定端口 BPDU(桥协议数据单元) STP利用BPDU选择根网桥 STP的收敛 VLAN与STP关系 MSTP多生成树协议华为 ...

  4. C语言:已知三角形三边长求面积

    //已知三角形三边长求面积 #include <stdio.h> #include <math.h> int main() { float a,b,c,p,s; int x=0 ...

  5. File类与常用IO流第九章——转换流

    第九章.转换流 字节编码和字符集 编码:按照某种规则将字符以二进制存储到计算机中. 解码:将存储在计算机中的二进制数按照某种规则解析显示出来. 字符编码:Character Encoding ,就是一 ...

  6. ES6 Class类

    在ES6中,class (类)作为对象的模板被引入,可以通过 class 关键字定义类.class 的本质是 function.它可以看作一个语法糖,让对象原型的写法更加清晰.更像面向对象编程的语法类 ...

  7. awk对某个字段分割处理

    工作中遇到要根据文件中某个字段分割成多行文本的处理,想到用awk处理,这里记录下: 问题: 原文件:假设一共2个字段,用"|"分割,其中第二个字段用"#"分割, ...

  8. P4334 [COI2007] Policija

    P4334 [COI2007] Policija 题意 一个无重边的无向图,每次询问删掉一条边或删掉一个点后两个点是否联通. 思路 连通性问题,我们可以考虑使用广义圆方树解决. 对于删掉一个点的情况: ...

  9. [考试总结]noip模拟16

    达成成就,一天更3篇总结. 又是一个暴力场 别问我为什么开局 \(5\) 分钟就问老师为什么 \(T3\) 没有提交的窗口. 开题读题,一路自闭到 \(T3\) ,发现 \(T3\) 可打暴力,所以一 ...

  10. C++第三十五篇 -- 写第一个驱动开发程序

    VS2017+WDK+VMware12+Win10环境配置完毕,接下来写第一个驱动程序. 1.新建一个KMDF的程序. 2.配置项目属性. 3.编译项目.一般这里应该成功,我一台电脑成功了,另一台电脑 ...