【BZOJ2322】[BeiJing2011]梦想封印 高斯消元求线性基+DFS+set
【BZOJ2322】[BeiJing2011]梦想封印
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
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
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;
题解:又一道神题
我们回忆2155那道题的做法:所有从1到一个点的路径的异或和 都可以表示成 任意一条从1到该节点的路径 和 某些简单环 的异或和。
那么本题变成了动态求异或和的种类数,我们首先的思路就是将删边变成倒着往图中加边。然后思考一下我们具体都需要维护些什么。
从答案的角度分析,答案=(所有本质不同的路径数)*2^(本质不同的环的个数)-1,注意本质不同的路径包括哪里都不走,所以最后要-1。具体本质不同是什么意思呢?
回忆2155那道题,本质不同的环的意思就是:将所有环高斯消元后得到的线性基,因为这样就可以表示任意环的异或和。
那么本质不同的路径的意思也就出来了,我们最终得到的不简单的路径的异或和=任意一条简单路径的异或和^任意一些环的异或和,所以两条简单路径本质不同当且仅当它们用线性基消元后,得到的值不同。具体地,我们可以用set来维护这样的路径。
好了,分析了这么多,现在我们终于可以得出一个可行的做法了:当加入边(a,b)时:
1.若a,b都已经被访问过(或者说加入的是一条非树边),我们此时得到了一个简单环,将这个简单环的异或和放到线性基中消元,如果没有消成0,那就说明我们应该将这个圆加入到线性基中去,直接把它加入到线性基中对应的位置就行了。但是注意一点,更改线性基后,之前的路径并没有被这条边消元,所以要把set里的边一个一个取出来,重新消元再塞回去。
2.若a被访问过b没有被访问过(或者说加入了一条树边),我们应该DFSb所在的连通块。在DFS的过程中,每搜到一个点,我们就计算出从1到这个点的路径的异或和,消元后看一下跟以前的是否重复,如果不重复就扔到set里。此外,每搜到一条树边,我们就继续向下搜索;每搜到一条非树边,我们就又得到了一个简单环,按照1中的处理方法去处理就行了。
3.若a,b都没有被访问过(我们也不知道它将会是树边还是非树边),不用管就好。
感觉实现要比理论简单一些。
#include <cstdio>
#include <cstring>
#include <iostream>
#include <set>
#include <algorithm>
typedef long long ll;
using namespace std;
int n,m,cnt,q;
int to[40010],next[40010],head[10010],pa[40010],pb[40010],del[40010],tag[40010],vis[10010];
ll val[40010],dis[10010],pc[40010],ans[40010];
ll v[110];
set<ll> s;
set<ll>::iterator it;
bool cmp(ll a,ll b)
{
return a>b;
}
ll query(ll x)
{
for(int j=1;j<=v[0];j++) if((x^v[j])<x) x^=v[j];
return x;
}
void updata(ll x)
{
if(!x) return ;
ll tmp;
for(it=s.begin();it!=s.end();it=s.upper_bound(tmp))
{
tmp=*it;
if((tmp^x)<tmp) s.erase(it),s.insert(tmp^x);
}
v[++v[0]]=x;
for(int j=v[0];j>=2;j--)
{
if(v[j]>v[j-1]) swap(v[j],v[j-1]);
else break;
}
}
void add(int a,int b,ll c)
{
to[cnt]=b,val[cnt]=c,next[cnt]=head[a],head[a]=cnt++;
}
void dfs(int x,int fa)
{
vis[x]=1;
ll tmp=query(dis[x]);
if(tmp&&s.find(tmp)==s.end()) s.insert(tmp);
for(int i=head[x];i!=-1;i=next[i])
{
if(to[i]==fa) continue;
if(!vis[to[i]]) dis[to[i]]=dis[x]^val[i],dfs(to[i],x);
else updata(query(dis[x]^dis[to[i]]^val[i]));
}
}
void insert(int a,int b,ll c)
{
add(a,b,c),add(b,a,c);
if(vis[a]&&vis[b])
{
updata(query(dis[a]^dis[b]^c));
return ;
}
if(!vis[a]&&!vis[b]) return ;
if(vis[b]) swap(a,b);
dis[b]=dis[a]^c,dfs(b,a);
}
int main()
{
memset(head,-1,sizeof(head));
vis[1]=1;
scanf("%d%d%d",&n,&m,&q);
int i;
for(i=1;i<=m;i++) scanf("%d%d%lld",&pa[i],&pb[i],&pc[i]);
for(i=1;i<=q;i++) scanf("%d",&del[i]),tag[del[i]]=1;
for(i=1;i<=m;i++) if(!tag[i]) insert(pa[i],pb[i],pc[i]);
s.insert(0);
ans[q+1]=(s.size()*1ll<<v[0])-1;
for(i=q;i>=1;i--)
{
insert(pa[del[i]],pb[del[i]],pc[del[i]]);
ans[i]=(s.size()*(1ll<<v[0]))-1;
}
for(i=1;i<=q+1;i++) printf("%lld\n",ans[i]);
return 0;
}
【BZOJ2322】[BeiJing2011]梦想封印 高斯消元求线性基+DFS+set的更多相关文章
- 【BZOJ2460】[BeiJing2011]元素 贪心+高斯消元求线性基
[BZOJ2460][BeiJing2011]元素 Description 相传,在远古时期,位于西方大陆的 Magic Land 上,人们已经掌握了用魔法矿石炼制法杖的技术.那时人们就认识到,一个法 ...
- 【BZOJ2115】[Wc2011] Xor 高斯消元求线性基+DFS
[BZOJ2115][Wc2011] Xor Description Input 第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目. 接下来M 行描述 M 条边,每行三个整数Si,Ti ...
- 【bzoj2115】[Wc2011] Xor DFS树+高斯消元求线性基
题目描述 输入 第一行包含两个整数N和 M, 表示该无向图中点的数目与边的数目. 接下来M 行描述 M 条边,每行三个整数Si,Ti ,Di,表示 Si 与Ti之间存在 一条权值为 Di的无向边. 图 ...
- 【bzoj3105】[cqoi2013]新Nim游戏 高斯消元求线性基
题目描述 传统的Nim游戏是这样的:有一些火柴堆,每堆都有若干根火柴(不同堆的火柴数量可以不同).两个游戏者轮流操作,每次可以选一个火柴堆拿走若干根火柴.可以只拿一根,也可以拿走整堆火柴,但不能同时从 ...
- 【bzoj4004】[JLOI2015]装备购买 贪心+高斯消元求线性基
题目描述 脸哥最近在玩一款神奇的游戏,这个游戏里有 n 件装备,每件装备有 m 个属性,用向量zi(aj ,.....,am) 表示 (1 <= i <= n; 1 <= j < ...
- 【bzoj4269】再见Xor 高斯消元求线性基
题目描述 给定N个数,你可以在这些数中任意选一些数出来,每个数可以选任意多次,试求出你能选出的数的异或和的最大值和严格次大值. 输入 第一行一个正整数N. 接下来一行N个非负整数. 输出 一行,包含两 ...
- HDU3949/AcWing210 XOR (高斯消元求线性基)
求第k小的异或和,用高斯消元求更简单一些. 1 //用高斯消元求线性基 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define ...
- 【BZOJ2844】albus就是要第一个出场 高斯消元求线性基
[BZOJ2844]albus就是要第一个出场 Description 已知一个长度为n的正整数序列A(下标从1开始), 令 S = { x | 1 <= x <= n }, S 的幂集2 ...
- BZOJ 4269 高斯消元求线性基
思路: 最大: 所有线性基异或一下 次大: 最大的异或一下最小的线性基 搞定~ //By SiriusRen #include <cstdio> #include <algorith ...
随机推荐
- python核心编程学习记录之正则表达式
- Spring管理的bean初始化方法的三种方式,以及@PostConstruct不起作用的原因
1:Spring 容器中的 Bean 是有生命周期的,spring 允许 Bean 在初始化完成后以及销毁前执行特定的操作.下面是常用的三种指定特定操作的方法: 通过实现InitializingBea ...
- Android 完美退出 App 方法
大家都知道 Android 的 Activity 是存着历史栈的,比如从 A -> B -> C,C 完成 finish 后回到 B,把所有的Activity 都 finish了,程序就自 ...
- 系统重装 Windows_VHD_辅助处理工具说明文档2
创建一个原始安装的VHD文件 如果采用原始安装的方式,则在WIN7的原始光盘中将install.wim这个文件提取到一个文件夹中备用.如果采用Ghost安装的方式,则将Ghost备份文件提取出来(.G ...
- 系统封装 EasyBoot如何将WIN7安装版提取到光盘
1 将WIN7光盘中的文件提取到Easyboot根目录,注意不要autorun.inf和setup.exe这两个文件.我们这里的Easyboot已经有了一些其他东西(XP的安装版文件,PE的文件等等, ...
- Input.GetAxis 获取轴
static function GetAxis (axisName : string) : float Description描述 Returns the value of the virtual a ...
- 怎样取消Macbook上顽固的开机启动项
博主遇到的一个顽固启动项是Cisco Anyconnect.我仅仅是偶尔须要使用VPN.可是安装了Cisco Anyconnect之后,每次开机它都会启动,非常烦人. 1 通过系统设置 首先,博主希望 ...
- quick-cocos2d-x教程9:实例之加上背景图片
在梳理完quick-cocos2d-x框架的各个文件夹后,我们開始我们的实例教程,在helloworld后面.加上一张图片,lua编辑器,我用的lua editor.还不错. 我们首先还是參照教程.创 ...
- SQL Server 中树形表数据的处理总结
-- 使用函数的方法: --建立 演示环境 if object_id('tb_bookInfo') is not null drop table tb_bookInfo go ),type int) ...
- oracle中sql执行性能关注点
繁琐复杂的执行计划.可能迷了开发人员的眼.导致一条性感又傻X的SQL 在服务器上跑得特欢乐 有介于此.重点抓住几个部分.至于其他的嘛.当然是.非礼勿视咯.. ㈠ 返回行的数量 ...