dtoj#4222. 小b爱旅行(travel)

题目描述:

小 $b$ 有一张无向图。

小 $b$ 可以从点 $1$ 出发,走任意一条路径,她将得到路径上的边的边权的异或值(一条边可能被经过多次,这时经过 几次就异或几次)。

路径可以为空,这时异或值为 $0$ 。

小 $b$ 想知道她能得到多少个不同的异或值。

小 $b$ 还会删掉 $q$ 条边,每删一条边,她都会问你一次。

数据范围:

对于全部数据:

$\bullet~1 \le n \le 10^5,1 \le m \le 2 \times 10^5,0 \le q \le m$;

$\bullet~1 \le x,y \le n,0 \le w \le 10^{18}$;

$\bullet~1 \le i \le m$且所有 $i$ 互不相同;

保证不存在重边和自环。

对于 $10 \%$ 的数据,$m \le 10$ 且 $q=0$ ;

对于另外 $30 \%$ 的数据,$w \le 1000$ 且 $q=0$ ;

对于另外 $30 \%$ 的数据,$q=0$ 。

算法标签:线性基

思路:

考虑对于一个环,是可以和任何一条路径异或得到的新的路径的。因为来回环上的点经过一次,来的路上经过的没有回路的路径,再回去的时候再走一次。

所以我们把环挑出来断成链,变成一棵生成树,跑出这棵树上的答案,然后把环的答案存进线性基中。

考虑如何把路径答案乘环的答案重复的时候,考虑对于线性基为1且路径答案为1的答案和对应为异或,最后得到的值互不相同,所有答案就会不相同。

对于断链,我们把他反过来做,当成是不断加边,那么每次对于没有加到1联通块的不做修改,对于新加的与1相连的点,重新dfs,如果对线性基造成改变,就重新统计所有点的答案。

效率是 $O(n\times3600\times logn)$   这个 $log$ 是 $map$ 的 $log$ 改成 $hash$ 表就可以省去这个 $logn$ ,但是因为数据没跑满能过,就这样吧。

以下代码:

#include<bits/stdc++.h>
#define il inline
#define LL long long
#define _(d) while(d(isdigit(ch=getchar())))
using namespace std;
const int N=1e5+5,M=4e5+5;
bool pd,tag[M];
LL w[M],dist[N],val[N],res[M],b[80],num;
map<LL,bool> ma;
int cnt,qr[M],tot;
int n,m,q,head[N],ne[M],to[M],d[N],f[N];
il LL read(){
    LL x;char ch;_(!);x=ch^48;
    _()x=(x<<1ll)+(x<<3ll)+(ch^48);
    return x;
}
il void ins(int x,int y,LL z){
    ne[++cnt]=head[x];head[x]=cnt;
    to[cnt]=y;w[cnt]=z;
}
il int getfa(int x){
    if(f[x]==x)return x;
    return f[x]=getfa(f[x]);
}
il void insert(LL x){
    for(int i=60;i>=0;i--){
        if(x&(1ll<<i)){
            if(b[i])x^=b[i];
            else{
                b[i]=x;tot++;
                pd=1;break;
            }
        }
    }
}
il void dfs1(int x,int fa){
    f[getfa(x)]=getfa(1);
    for(int i=head[x];i;i=ne[i]){
        if(fa==to[i]||tag[i])continue;
        if(!d[to[i]]){
            dist[to[i]]=dist[x]^w[i];
            d[to[i]]=d[x]+1;dfs1(to[i],x);
        }
        else{
            insert(dist[x]^dist[to[i]]^w[i]);
        }
    }
}
il LL C(LL x){
    for(int i=60;i>=0&&x;i--){
        if(b[i]&&(x>>i&1))x^=b[i];
    }
    return x;
}
il void add(int x){
    val[x]=C(dist[x]);
    if(!ma[val[x]])num++,ma[val[x]]=1;
}
il void dfs2(int x,int fa){
    f[getfa(x)]=getfa(1);add(x);
    for(int i=head[x];i;i=ne[i]){
        if(fa==to[i]||tag[i])continue;
        if(!d[to[i]]){
            dist[to[i]]=dist[x]^w[i];
            d[to[i]]=d[x]+1;
            dfs2(to[i],x);
        }
        else{
            insert(dist[x]^dist[to[i]]^w[i]);
        }
    }
}
il void rebuild(){
    num=0;
    for(int i=1;i<=n;i++)if(d[i])ma[val[i]]=0;
    for(int i=1;i<=n;i++)if(d[i])add(i);
}
int main()
{
    n=read();m=read();q=read();
    for(int i=1;i<=n;i++)f[i]=i;
    for(int i=1;i<=m;i++){
        int x=read(),y=read();LL w=read();
        ins(x,y,w);ins(y,x,w);
    }
    for(int i=1;i<=q;i++){
        int x=read();qr[i]=x;
        tag[x<<1]=tag[(x<<1)-1]=1;
    }
    d[1]=1;dfs1(1,0);
    for(int i=1;i<=n;i++)if(d[i])add(i);
    for(int i=q;i;i--){
        res[i]=(1ll<<tot)*num;tag[qr[i]<<1]=tag[(qr[i]<<1)-1]=0;
        int a=to[qr[i]<<1],b=to[(qr[i]<<1)-1];
        int x=getfa(a),y=getfa(b);
        if(x==y){
            if(x^getfa(1))continue;
            pd=0;
            insert(dist[a]^dist[b]^w[qr[i]<<1]);
            if(pd)rebuild();
        }
        else{
            if(y==getfa(1))swap(x,y),swap(a,b);
            f[y]=x;
            if(x^getfa(1))continue;
            dist[b]=dist[a]^w[qr[i]<<1];
            pd=0;d[b]=d[a]+1;dfs2(b,a);
            if(pd)rebuild();
        }
    }
    res[0]=(1ll<<tot)*num;
    for(int i=0;i<=q;i++)printf("%lld\n",res[i]);
    return 0;
}

原文地址:https://www.cnblogs.com/Jessie-/p/10454416.html

时间: 2024-10-14 13:54:51

dtoj#4222. 小b爱旅行(travel)的相关文章

Geek爱旅行 - 仗剑走天涯

记得刚毕业的时候,也就是2004年,那时的我还在郑州,一个月三千,过了试用期转正又涨了两千,特别开心.虽然路不好走,每天要处理的问题都是自己不会的,但是慢慢习惯了这种生活带来的压力,由于小地方的坑比较多,工资没有按时发过,自己的日子过的很清贫,学弟学妹眼中的骄傲,生活中却是失魂落魄.尽管每周母亲总是关心的打电话,问自己生活如何,身体如何,工作如何,自己还是违心的让母亲安心,一切都好~回想起郑州每天站在阳台仰望街边远处的星辰和灯火时,总是无声无息的让自己没有了期盼.不过还好,并没有失去动力让自己继

【vijos】1746 小D的旅行(dijkstra)

https://vijos.org/p/1746 这题就是水题.裸的跑完每个点的最短路后直接可以暴力出解.. 这题贴出来是因为我改了下我的dijkstra的模板... 注意vis不要提前加.否则你懂的.. #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #in

Geek爱旅行 - 藏在回忆里的那个人

在那个云淡风轻的日子,听风吹过的时光,是我们最好的年纪~像青春的岁月在回忆里浮动,你的梦里有没有她的... 藏在我回忆里的那个人,现在你过得还算幸福安稳,盼望不久相遇在人海黄昏,依然记得你当年坚强的眼神,一个人扛起一切的认真. 我的青春,也不是没伤痕,是明白爱是信仰的延伸,什么特征,人缘还是眼神,也不会预知爱不爱的可能. 保持单身,忍不住又沉沦,兜着圈子来去有时苦等,人的一生,感情是旋转门,转到了最后真心的就不分. 有过竞争,有过牺牲,被爱筛选过程,学会认真,学会忠诚,适者才能生存,懂得永恒,得

Geek爱旅行 - 穿越时间的旅行

每条路都是孤独的,慢慢的你会相信没有什么事不可原谅,也许现在的你很累,未来的路还很长,不要忘了当初为何而出发,是什么让你坚持到现在,勿忘初心.丢失的自己 ,只能一点一点找回来 ,让自己变得优秀,是为了让爱你的人骄傲. [穿越时间的旅行] 女生无理取闹的时候其实自己内心都清楚这么做是挺无理的,但女生就是这样,喜欢通过一些小事来证明,即使她错了,你也会让着,这对你来说,也许是没事找事,可对她来说,你是她想嫁给的人,那时她是要离开父母的呵护从此跟随在你身旁,未来与你生命相关,托付终身. 给你系鞋带的人

小a的旅行计划(BM模板)

题目链接:https://ac.nowcoder.com/acm/contest/223/B 题目大意: 小a终于放假了,它想在假期中去一些地方游玩,现在有N个景点,编号为1,2,…N1,2,…N,同时小b也想出去游玩.由于一些特殊♂原因,他们的旅行计划必须满足一些条件 首先,他们可以从这N个景点中任意选几个游玩 设小a选出的景点集合为A,小b选的景点集合为B,则需要满足 1. A,B的交集不能为空集 2. A,B不能相互包含(A=B也属于相互包含) 注意:在这里我们认为(A,B)是无序的,即(

【洛谷T4896】小Z爱划水

题目描述 小Z和其它机房同学都面临一个艰难的抉择,那就是 要不要划水? 每个人都有自己的一个意见,有的人想做题,有的人想划水. 当然,每个人只能选择一个事情做.如果一个人做的事情和他想做的不同,那么他会产生1不满意度. 更棘手的是,他们之间一些人是朋友,如果两人是朋友,但是他们做的事情不同,那么会有1不满意度产生. 小Z不想看到大家闹得不高兴,他想知道,不满意度最小能是多少? 输入输出格式 输入格式: 第一行两个数字n,m 分别表示有n个人和m对朋友关系 第二行n个0/1,1表示想做题,0表示想

小鑫爱运动

题目描述 小鑫非常喜欢运动,有一次小鑫去参加110米栏的比赛,一共有10名比赛选手,小鑫是1号,由于跑的太专注,最后冲线的时候不知道自己是第几名,只知道每个人最后的成绩,聪明的你可不可以帮帮他? 输入 多组输入. 先输入一个10, 然后每组输入10个整数,代表10个选手的110米栏成绩m,代表1号到N号的N个选手的成绩m,m范围是(0 < m < 100). 输出 输出只有一行,代表小鑫最后的名次是多少. 因为小鑫长得比较丑,所以如果成绩相同的情况下,小鑫都会排在前面. 示例输入 10 2 5

小Z爱划水

题目背景 小Z在机房. 题目描述 小Z和其它机房同学都面临一个艰难的抉择,那就是 要不要划水? 每个人都有自己的一个意见,有的人想做题,有的人想划水. 当然,每个人只能选择一个事情做.如果一个人做的事情和他想做的不同,那么他会产生1不满意度. 更棘手的是,他们之间一些人是朋友,如果两人是朋友,但是他们做的事情不同,那么会有1不满意度产生. 小Z不想看到大家闹得不高兴,他想知道,不满意度最小能是多少? 输入输出格式 输入格式: 第一行两个数字n,m 分别表示有n个人和m对朋友关系 第二行n个0/1

【0521模拟赛】小Z爱数学

题目描述 小Z想求F(n,k),F(n,k)表示n的所有因数pi中,满足n/pi <= k 的和. 小Z发现还是很水,所以他决定加大难度. 求 小Z还准备了很多个询问.现在你来解决一下吧. 输入输出格式 输入格式: 第一行两个整数m 表示询问的个数 接下来每行两个数ni,ki,表示这个询问的n和k 输出格式: , 也就是把刚好等于k的答案加进去  然后k变大 对于每个询问输出一行一个整数,表示对应的答案. 题目理解:F(n,k)表示n的所有因数qi中,满足n/qi<=k的和, m组,每组给定n