Codeforces 题目传送门 & 洛谷题目传送门

一道线性基的综合题 %%%%%%

首先注意到“非简单路径”“异或和”等字眼,可以本能地想到线性基。根据线性基那一套理论,一个值 \(v\) 可以表示为某个 \(1\to 1\) 的非简单回路上边权的异或和当前节点它可以表示为 \(1\) 所在连通块的若干个 \(\ge 1\) 简单环上权值的异或和。其次我们还可以注意到本题至于很小,最高不过 \(2^5-1=31\),而稍微打个表即可发现大小为 \(5\) 的本质不同的线性基个数只有 \(374\) 个,因此可以暴搜求出所有本质不同的线性基,具体来说我们每次枚举 \(i=1,2,3,\cdots,31\),如果当前线性基里能够插入 \(i\) 就插入 \(i\) 并继续 DFS 下去,复杂度 \(374\times 31\times 5\),不会出问题。

然后考虑以线性基为状态的 DP,我们假设去掉 \(1\) 号点之后原图有 \(m\) 个连通块,注意到我们只能删除与 \(1\) 相连的边,故每个连通块内部环的情况是不受影响的,因此我们可以先按照 P4151 [WC2011]最大XOR和路径 的套路求出每个连通块中所有环的异或和组成的线性基,当然如果这个线性基是线性有关集那说明如果这个连通块如果与 \(1\) 相连就会存在不合法的路径,也就是说这个连通块必须与 \(1\) 断开,这个维护一个数组 \(ok_i\) 表示编号为 \(i\) 的连通块是否合法即可。不难发现每个连通块只可能有两种可能,一是连通块内部存在一个与 \(1\) 相连的点,二是连通块内部存在两个与 \(1\) 相连的点,不可能出现三个及以上与 \(1\) 相连的点,否则就会出现长度 \(>3\) 的经过 \(1\) 的环了,记 \(dp_{i,j}\) 为考虑前 \(i\) 个连通块,当前线性基为 \(j\)(我们将大小为 \(5\) 的本质不同的线性基编号 \(1,2,3,\cdots,374\))的方案数,考虑按照上面的分析过程分情况讨论:

  • 若 \(ok_i=0\),那么 \(1\) 与当前连通块之间的边必须断开,即 \(dp_{i,j}=dp_{i-1,j}\)
  • 若 \(ok_i=1\),继续分两种情况:
    • 连通块内部存在一个与 \(1\) 相连的点,记 \(b_i\) 为连通块 \(i\) 的线性基,那么如果断开与 \(1\) 相连的边线性基不会发生变化,即 \(dp_{i,j}\leftarrow dp_{i-1,j}\),否则相当于将线性基 \(j\) 与 \(b_i\) 进行合并,即 \(dp_{i,j\cup b_i}\leftarrow dp_{i-1,j}\)
    • 连通块内部存在两个与 \(1\) 相连的点,如果断开两条与 \(1\) 相连的边,线性基不会发生变化,即 \(dp_{i,j}\leftarrow dp_{i-1,j}\),如果断开一条与 \(1\) 相连的边,相当于将线性基 \(j\) 与 \(b_i\) 进行合并,即 \(dp_{i,j\cup b_i}\leftarrow 2·dp_{i-1,j}\),如果与 \(1\) 相连的边都不断开,那么这部分会多出一个环没有加入线性基,这个环就是经过 \(1\) 的三元环,记 \(w\) 为该三元环的权值异或和,那么 \(dp_{i,j\cup b_i\cup w}\leftarrow dp_{i-1,j}\)

预处理线性基的合并关系即可在常数时间内实现转移,时间复杂度 \(155\times 374+374^2+374n\)

const int MAXN=1e5;
const int MAXB=380;
const int MOD=1e9+7;
int n,m;
struct lbase{
int a[5];
lbase(){memset(a,0,sizeof(a));}
bool insert(int x){
for(int i=4;~i;i--) if(x>>i&1){
if(a[i]) x^=a[i];
else{
a[i]=x;
for(int j=0;j<i;j++) if(a[i]>>j&1) a[i]^=a[j];
for(int j=i+1;j<=4;j++) if(a[j]>>i&1) a[j]^=a[i];
return 1;
}
} return 0;
}
int hash(){return (a[4]<<10)|(a[3]<<6)|(a[2]<<3)|(a[1]<<1)|a[0];}
} b[MAXB+5],c[MAXN+5];
int rid[MAXN+5],num=0;
void dfsfind(lbase cur){
int hs=cur.hash();if(rid[hs]) return;
else rid[hs]=++num,b[num]=cur;
for(int i=1;i<=31;i++){
lbase nxt=cur;
if(nxt.insert(i)) dfsfind(nxt);
}
}
int trs[MAXB+5][MAXB+5];
void init_trs(){
for(int i=1;i<=num;i++) for(int j=1;j<=num;j++){
lbase tmp=b[i];bool ok=1;
for(int k=0;k<=4;k++) if(b[j].a[k]) ok&=tmp.insert(b[j].a[k]);
if(ok) trs[i][j]=rid[tmp.hash()];
}
}
int hd[MAXN+5],to[MAXN*2+5],val[MAXN*2+5],nxt[MAXN*2+5],ec=0;
void adde(int u,int v,int w){to[++ec]=v;val[ec]=w;nxt[ec]=hd[u];hd[u]=ec;}
int bel[MAXN+5],dis[MAXN+5],ok[MAXN+5],cmp=0,con[MAXN+5],fst[MAXN+5];
bool is[MAXN+5];int dfn[MAXN+5],tim=0;
void dfs(int x,int f){
bel[x]=cmp;dfn[x]=++tim;
for(int e=hd[x];e;e=nxt[e]){
int y=to[e],z=val[e];if(y==1) continue;
if(!bel[y]) dis[y]=dis[x]^z,dfs(y,x);
else if(y!=f&&dfn[x]>dfn[y]) ok[cmp]&=c[cmp].insert(dis[x]^dis[y]^z);
}
}
int dp[MAXN+5][MAXB+5];
int main(){
scanf("%d%d",&n,&m);dfsfind(*new(lbase));init_trs();
for(int i=1,u,v,w;i<=m;i++){
scanf("%d%d%d",&u,&v,&w);
adde(u,v,w);adde(v,u,w);
} //printf("%d\n",num);
for(int e=hd[1];e;e=nxt[e]){
int y=to[e],z=val[e];
if(!bel[y]){
cmp++;ok[cmp]=1;con[cmp]=z;
fst[cmp]=y;dfs(y,-1);
} else {
for(int ee=hd[y];ee;ee=nxt[ee]){
int v=to[ee],w=val[ee];
if(v==fst[bel[y]]){
is[bel[y]]=1;con[bel[y]]^=w^z;
break;
}
}
}
}
dp[0][rid[0]]=1;
for(int i=1;i<=cmp;i++){
for(int j=1;j<=num;j++) dp[i][j]=dp[i-1][j];
if(!ok[i]) continue;
if(!is[i]){
int id=rid[c[i].hash()];
for(int j=1;j<=num;j++) if(trs[j][id]){
dp[i][trs[j][id]]=(dp[i][trs[j][id]]+dp[i-1][j])%MOD;
}
} else {
int id1=rid[c[i].hash()];
bool ok=c[i].insert(con[i]);
int id2=rid[c[i].hash()];
for(int j=1;j<=num;j++){
if(trs[j][id1]) dp[i][trs[j][id1]]=(dp[i][trs[j][id1]]+2*dp[i-1][j]%MOD)%MOD;
if(ok&&trs[j][id2]) dp[i][trs[j][id2]]=(dp[i][trs[j][id2]]+dp[i-1][j]%MOD)%MOD;
}
}
} int ans=0;
for(int i=1;i<=num;i++) ans=(ans+dp[cmp][i])%MOD;
printf("%d\n",ans);
return 0;
}

Codeforces 1299D - Around the World(线性基+图论+dp)的更多相关文章

  1. 洛谷P4151 最大XOR和路径 [WC2011] 线性基+图论

    正解:线性基+图论 解题报告: 传送门 首先可以思考一下有意义的路径会是什么样子,,,那就一定是一条链+一些环 挺显然的因为一条路径原路返回有没有意义辣?所以一定是走一条链+一些环(当然也可以麻油环, ...

  2. 【做题】CF388D. Fox and Perfect Sets——线性基&数位dp

    原文链接https://www.cnblogs.com/cly-none/p/9711279.html 题意:求有多少个非空集合\(S \subset N\)满足,\(\forall a,b \in ...

  3. Codeforces 938G 线段树分治 线性基 可撤销并查集

    Codeforces 938G Shortest Path Queries 一张连通图,三种操作 1.给x和y之间加上边权为d的边,保证不会产生重边 2.删除x和y之间的边,保证此边之前存在 3.询问 ...

  4. 【题解】 Codeforces 662A Gambling Nim (线性基)

    662A,戳我戳我 Solution: 我们先取\(ans=a[1] \bigoplus a[2] \bigoplus ... \bigoplus a[n]\),然后我们定义\(c[i]=a[i] \ ...

  5. codeforces 1100F Ivan and Burgers 线性基 离线

    题目传送门 题意: 给出 n 个数,q次区间查询,每次查询,让你选择任意个下标为 [ l , r ] 区间内的任意数,使这些数异或起来最大,输出最大值. 思路:离线加线性基. 线性基学习博客1 线性基 ...

  6. [bzoj 2115]线性基+图论

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2115 给定一个带权无向图,要找出从1到n路径权值异或和最大的那一条的路径异或和. 考虑1到 ...

  7. BZOJ CF388D. Fox and Perfect Sets [线性基 数位DP]

    CF388D. Fox and Perfect Sets 题意:求最大元素\(le n\)的线性空间的个数 给神题跪了 orz 容易想到 每个线性基对应唯一的线性空间,我们可以统计满足条件的对应空间不 ...

  8. bzoj 3811: 玛里苟斯【线性基+期望dp】

    这个输出可是有点恶心啊--WA*inf,最后抄了别人的输出方法orz 还有注意会爆long long,要开unsigned long long 对于k==1,单独考虑每一位i,如果这一位为1则有0.5 ...

  9. codeforces 388D Fox and Perfect Sets(线性基+数位dp)

    #include<bits/stdc++.h> using namespace std; #define fi first #define se second #define mp mak ...

随机推荐

  1. Java:volatile笔记

    Java:volatile笔记 本笔记是根据bilibili上 尚硅谷 的课程 Java大厂面试题第二季 而做的笔记 1. volatile 和 JMM 内存模型的可见性 JUC 下的三个包 java ...

  2. [对对子队]会议记录4.11(Scrum Meeting 2)

    今天已完成的工作 何瑞 ​ 工作内容:完成指令的衔接:完成合成指南界面的制作:初步实现成本系统 ​ 相关issue:实现用户指令编辑系统的逻辑 马嘉 ​ 工作内容:完成游戏内暂停界面 ​ 相关issu ...

  3. FastAPI 学习之路(三十三)操作数据库

    通过创建pydantic模型进行验证提交数据 from pydantic import BaseModel class UserBase(BaseModel): email: str class Us ...

  4. SpringCloud 2020.0.4 系列之服务降级的其他用法与熔断

    1. 概述 老话说的好:控制好自己的情绪,才能控制好自己的人生.冲动是魔鬼,冷静才最重要. 言归正传,之前聊了在 Feign 调用时,如何给整个 Feign接口类 增加降级策略. 今天我们来聊一下 H ...

  5. [调试笔记] 晚测5 T1 容易题

    众所周知,sbwzx在考试一结束就嚷嚷T1是个sb题.那他为什么调了2小时才调出来呢?快和小编一起看看吧. Sb题:指除了sbwzx别人都能做出来的题 1.CE:震惊!sbwzx竟然连map都不会用, ...

  6. [调试笔记] 10.8模拟赛11 T4 甜圈

    这题正解线段树维护哈希,同机房神犇已经讲的很明白了.这里只说sbwzx在调试的时候犯的sb错误. 1.关于pushdown和update 众所周知,sbwzx一写带lazy的线段树,就必在pushdo ...

  7. 手写vue-router & 什么是Vue插件

    博文分享 这篇文章你可以学习到: 实现一个自己的vue-router 了解什么是Vue的插件 学习b站大佬后做的笔记整理和源码实现 1.1.3一步一步带你弄懂vue-router核心原理及实现哔哩哔哩 ...

  8. OpenWrt编译报错:Package airfly_receiver is missing dependencies for the following libraries

    今天在编译一个OpenWrt测试用例的时候出现报错 Package airfly_receiver is missing dependencies for the following librarie ...

  9. js 在浏览器中的event loop事件队列

    目录 前言 认识一个栈两个队列 执行过程 异步任务怎么分配 简单例子 难一点的例子 前言 以下内容是js在浏览器中的事件队列执行,与在nodejs中有所区别,请注意. 都说js是单线程的,不过它本身其 ...

  10. IDEA升级开源框架

    在开发过程中,我们经常会用到一些 GitHub或者Gitee上的开源框架来快速搭建我们的业务系统,但是当框架被我们大批量修改后,开源框架又有升级了.这时候升级框架就变得很麻烦,也不能直接直接进行合并, ...