[BZOJ 2322][BeiJing2011]梦想封印
梦想封印
题意
原题面:
Problem 2322. -- [BeiJing2011]梦想封印
2322: [BeiJing2011]梦想封印
Time Limit: 20 Sec Memory Limit: 128 MB
Submit: 607 Solved: 240
[Submit][Status][Discuss]
Description
渐渐地,Magic Land上的人们对那座岛屿上的各种现象有了深入的了解。
为了分析一种奇特的称为梦想封印(Fantasy Seal)的特技,需要引入如下的概念:
每一位魔法的使用者都有一个“魔法脉络”,它决定了可以使用的魔法的种类。
一般地,一个“魔法脉络”可以看作一个无向图,有N个结点及M条边,将结点编号为1~N,其中有一个结点是特殊的,称为核心(Kernel),记作1号结点。每一条边有一个固有(即生成之后再也不会发生变化的)权值,是一个不超过U的自然数。
每一次魔法驱动,可看作是由核心(Kernel)出发的一条有限长的道路(Walk),可以经过一条边多次,所驱动的魔法类型由以下方式给出:
将经过的每一条边的权值异或(xor)起来,得到s。
如果s是0,则驱动失败,否则将驱动编号为s的魔法(每一个正整数编号对应了唯一一个魔法)。
需要注意的是,如果经过了一条边多次,则每一次都要计入s中。
这样,魔法脉络决定了可使用魔法的类型,当然,由于魔法与其编号之间的关系尚未得到很好的认知,此时人们仅仅关注可使用魔法的种类数。
梦想封印可以看作是对“魔法脉络”的破坏:
该特技作用的结果是,“魔法脉络”中的一些边逐次地消失。
我们记总共消失了Q条边,按顺序依次为Dis1、Dis2、……、DisQ。
给定了以上信息,你要计算的是梦想封印作用过程中的效果,这可以用Q+1个自然数来描述:
Ans0为初始时可以使用魔法的数量。
Ans1为Dis1被破坏(即边被删去)后可以使用魔法的数量。
Ans2为Dis1及Dis2均被破坏后可使用魔法的数量。
……
AnsQ为Dis1、Dis2、……、DisQ全部被破坏后可以使用魔法的数量。
Input
第一行包含三个正整数N、M、Q。
接下来的M行,每行包含3个整数,Ai、Bi、Wi,表示一条权为Wi的与结点Ai、Bi关联的无向边,其中Wi是不超过U的自然数。
接下来Q行,每行一个整数:Disi。
Output
一共包Q+1行,依次为Ans0、Ans1、……、AnsQ。
Sample Input
【输入样例1】
3 3 2
1 2 1
2 3 2
3 1 4
1
3
【输入样例2】
5 7 7
1 2 1
1 3 1
2 4 2
2 5 2
4 5 4
5 3 9
4 3 1
7
6
5
4
3
2
1
Sample Output
【输出样例1】
5
2
0
【样例1解释】
初始时可使用编号为1、3、4、6、7的魔法。
在删去第1条边(连结1、2结点的边)后,可使用4和6号魔法。
第3条边(连结第1、3结点的边)也被删去后,核心(Kernel)即结点1孤立,易知此时无法使用魔法。
【输出样例2】
15
11
5
2
2
1
1
0
HINT
【数据规模和约定】
所有数据保证该无向图不含重边、自环。所有数据保证不会有一条边被删除多次,即对于不同i和j,有Disi≠Disj
30%的数据中N ≤ 50,M ≤ 50,Q ≤50,U≤100;
60%的数据中N ≤ 300,M ≤ 300,Q ≤50,U≤10^9;
80%的数据中N ≤ 300,M ≤ 5000,Q ≤5000,U≤10^18;
100%的数据中N ≤ 5000,M ≤ 20000,Q ≤20000,U≤10^18;
Source
给定一张无向带权有根图, 求从根出发的任意一条路径上的边的异或和的种类数量.
题解
果然车万题不少都是高端题
首先如果这题是树的话其实就等价于求根到所有结点的异或和. 因为跑到其他地方必定要跑回来于是就又把原来的贡献异或掉了
所以问题在于环.
考虑一个环会产生什么高端操作? 沿着环走一圈回到原点, 然后总贡献变了.
也就是说对于环我们可以任意选择要不要加入路径贡献中. (走过去再走回来, 沿途的贡献便被消去了)
对于环的情况我们求一遍线性基那么对于种类的贡献就是 \(2^k\) 了
然后考虑剩下的简单路径. (作出贡献的必然是简单路径. 重复的会抵消. 于是等价于从根出发到所有其他结点的路径)
注意到只有DFS树上的简单路径是有用的(如果有多种方案可以从根到达某个点, 那么另一条路径的贡献可以通过树上路径异或上一个环得到). 于是有用的路径只有 \(O(V)\) 条.
用环的线性基消这些简单路径, 剩下的杂值就是无法被表出的部分, 也就是这个简单路径的特殊部分. 如果两个路径的特征值相等, 那么其中一个路径选一些环后得到的值必然也可以在另一条路径的基础上选一些环表出. 那么它们对总方案作出的贡献是重复的. 需要去重.
所以把这些值丢到 set
里就好了
最后的答案就是 \(p\times 2^k-1\). \(p\) 是 set
的大小, \(k\) 是线性基的大小. \(-1\) 是因为 \(0\) 的情况不做贡献.
然而上面解决的是静态问题
动态删边果断离线然后变成加边.
考虑加入一条边后有什么高端操作. 假设加入的边端点为 \(u,v\).
- 如果 \(u\) 和 \(v\) 都不与根连通, 则这条边对答案没有贡献, 先扔着就好了
- 如果 \(u\) 和 \(v\) 中有一个与根联通, 那么 \(v\) 所在的整个联通块都可以作出贡献,
DFS
计算这些贡献.- 首先计算根到这个点的树上路径的异或和, 用线性基消一下丢到
set
里 - 如果遇到了环, 把它插入线性基. 然后用新的线性基更新整个
set
.
- 首先计算根到这个点的树上路径的异或和, 用线性基消一下丢到
- 如果 \(u\) 和 \(v\) 都与根联通, 则一定有一个环出现. 注意到只要把其中一个包含边 \((u,v)\) 的环丢进线性基就可以了, 其他的新环都可以通过原来已经存在的环异或上这个环构造出来. 那么我们直接选最容易搞的环, 把根到 \(u\) 的异或和异或上根到 \(v\) 的异或和最后异或上边 \((u,v)\) 的值就可以得到一个环的值了, 插进线性基即可.
预处理也可以参考上面的策略用一次 DFS
解决.
参考代码
#include <bits/stdc++.h>
const int MAXV=5010;
const int MAXE=1e5+10;
typedef long long intEx;
struct Edge{
int from;
int to;
intEx val;
Edge* next;
};
Edge E[MAXE];
Edge Ex[MAXE];
Edge* head[MAXV];
Edge* top=E;
int v;
int e;
int q;
int brk[MAXE];
int pos[MAXE];
int prt[MAXV];
bool vis[MAXV];
intEx sum[MAXV];
intEx ans[MAXE];
std::set<intEx> path;
std::vector<intEx> base;
void DFS(int);
inline intEx Elim(intEx);
inline intEx Insert(intEx);
inline void AddCycle(intEx);
inline void Insert(int,int,intEx);
int main(){
scanf("%d%d%d",&v,&e,&q);
for(int i=1;i<=e;i++)
scanf("%d%d%lld",&Ex[i].from,&Ex[i].to,&Ex[i].val);
for(int i=1;i<=q;i++){
scanf("%d",pos+i);
brk[pos[i]]=i;
}
for(int i=1;i<=e;i++){
if(brk[i]==0){
Insert(Ex[i].from,Ex[i].to,Ex[i].val);
Insert(Ex[i].to,Ex[i].from,Ex[i].val);
}
}
DFS(1);
ans[q]=(intEx(path.size())<<base.size())-1;
for(int i=q;i>0;i--){
Edge* k=Ex+pos[i];
Insert(k->from,k->to,k->val);
Insert(k->to,k->from,k->val);
int cnt=vis[k->from]+vis[k->to];
if(cnt==2)
AddCycle(sum[k->from]^sum[k->to]^k->val);
else if(cnt==1){
if(vis[k->from]){
sum[k->to]=sum[k->from]^k->val;
DFS(k->to);
}
else{
sum[k->from]=sum[k->to]^k->val;
DFS(k->from);
}
}
ans[i-1]=(intEx(path.size())<<base.size())-1;
}
for(int i=0;i<=q;i++)
printf("%lld\n",ans[i]);
return 0;
}
void AddCycle(intEx val){
if((val=Insert(val))){
std::set<intEx> tmp;
for(auto i:path)
tmp.insert(std::min(i,i^val));
std::swap(tmp,path);
}
}
void DFS(int root){
vis[root]=true;
path.insert(Elim(sum[root]));
for(Edge* i=head[root];i!=NULL;i=i->next){
if(vis[i->to])
AddCycle(sum[root]^sum[i->to]^i->val);
else{
sum[i->to]=sum[root]^i->val;
DFS(i->to);
}
}
}
inline intEx Elim(intEx x){
for(auto i:base)
x=std::min(x,x^i);
return x;
}
inline intEx Insert(intEx x){
x=Elim(x);
if(x!=0)
base.push_back(x);
return x;
}
inline void Insert(int from,int to,intEx val){
top->from=from;
top->to=to;
top->val=val;
top->next=head[from];
head[from]=top++;
}
[BZOJ 2322][BeiJing2011]梦想封印的更多相关文章
- 【BZOJ2322】[BeiJing2011]梦想封印 高斯消元求线性基+DFS+set
[BZOJ2322][BeiJing2011]梦想封印 Description 渐渐地,Magic Land上的人们对那座岛屿上的各种现象有了深入的了解. 为了分析一种奇特的称为梦想封印(Fantas ...
- BZOJ2322: [BeiJing2011]梦想封印
Description 渐渐地,Magic Land上的人们对那座岛屿上的各种现象有了深入的了解. 为了分析一种奇特的称为梦想封印(Fantasy Seal)的特技,需要引入如下的概念: 每一位魔法的 ...
- 【线性基】bzoj2322: [BeiJing2011]梦想封印
线性基的思维题+图常见套路 Description 渐渐地,Magic Land上的人们对那座岛屿上的各种现象有了深入的了解. 为了分析一种奇特的称为梦想封印(Fantasy Seal)的特技,需要引 ...
- 【BZOJ 2322】[BeiJing2011]梦想封印 利用"环基"+线性基特征值
很容易想到离线加边并且把环和链拆开搞(就是对于每个终点求出起点到他的路径(其实就是dfs树),然后bzoj2115),而且维护也很简单,然而我们发现不同的终点可能得到相同的值,这就是我们遇到的最大的问 ...
- BZOJ2322 [BeiJing2011]梦想封印 【set + 线性基】
题目链接 BZOJ2322 题解 鉴于BZOJ2115,要完成此题,就简单得多了 对图做一遍\(dfs\),形成\(dfs\)树,从根到每个点的路径形成一个权值,而每个返祖边形成一个环 我们从根出发去 ...
- BZOJ 2462: [BeiJing2011]矩阵模板
2462: [BeiJing2011]矩阵模板 Time Limit: 2 Sec Memory Limit: 128 MBSubmit: 915 Solved: 432[Submit][Stat ...
- 【贪心】Bzoj 2457:[BeiJing2011]双端队列
2457: [BeiJing2011]双端队列 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 209 Solved: 95[Submit][Stat ...
- BZOJ 2460: [BeiJing2011]元素
2460: [BeiJing2011]元素 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 878 Solved: 470[Submit][Statu ...
- BZOJ:2460[BeiJing2011]元素 (异或基+贪心)
2460: [BeiJing2011]元素 Time Limit: 20 Sec Memory Limit: 128 MBSubmit: 2910 Solved: 1535 题目链接:https: ...
随机推荐
- ibatis内置类型
别名 java类型 事务管理器类型 JDBC com.ibatis.sqlmap.engine.transaction.jdbc.JdbcTransactionConfig JTA com.iba ...
- FocusBI: SSIS 开发案例(原创)
关注微信公众号:FocusBI 查看更多文章:加QQ群:808774277 获取学习资料和一起探讨问题. <商业智能教程>pdf下载地址 链接:https://pan.baidu.com/ ...
- GBK 编码
GBK编码范围:8140-FEFE,汉字编码范围见第二节:码位分配及顺序. GBK编码,是对GB2312编码的扩展,因此完全兼容GB2312-80标准.GBK编码依然采用双字节编码方案,其编码范围:8 ...
- JDK1.7新特性(2):异常和可变长参数处理
异常 jdk1.7对try--catch--finally的异常处理模式进行了增强,下面我们依次来看增强的方面. 1. 为了防止异常覆盖,给Throwable类增加了addSuppressed方法,可 ...
- linux ssh 免密码登录的配置过程
# ssh-keygen -t rsa -C "自定义描述" -f ~/.ssh/自定义生成的rsa文件 # cd ./.ssh # touch config # 粘贴 Host ...
- JAVA练手--线程(Thread)
1. 查看线程是否还存活 package tet;public class kk extends Thread{ //1. 查看线程是否还存活 public void run(){ for(int i ...
- [转]在windows service中使用timer
本文转自:http://blog.csdn.net/sharpnessdotnet/article/details/7637180 一定要使用System.Timers.Timer timer 而不是 ...
- No Mapping For GET "xxx.do"
今天写的一个form表单提交时总是报错找不到mapping,form如下: <form action="toUpdate.do" method="post" ...
- 【我整理的java开源项目】
摘要: 1. 整理出一些使用比较广或者个人觉得比较好的java开源项目和资料供参考. 2. 如果你觉得好但是我没有列出的开源项目请告诉我,方便我添加到列表里. 3. 如果你发现信息描述有误请联系我,我 ...
- Socket的基本操作
socket的基本操作: (1)socket()函数: (2)bind()函数: (3)listen(),connect()函数: (4)accept()函数: (5)socket中的发送与接收函数: ...