3069: [Pa2011]Hard Choice 艰难的选择

Description

Byteasar是一个很纠结的人。每次他经过Bytetown的时候都知道有至少2条不同的路径可以选择,这导致他必须花很长时间来决定走哪条路。Byteasar最近听说了Bytetown的修路计划,他可能是唯一一个为此感到高兴的人——他有机会消除他的烦恼。

在Byteasar一共有n个岔口,连接着m条双向道路。两条路径完全不同当且仅当他们没有公共的道路(但是允许经过相同的岔口)。

Byteasar想知道:对于两个岔口x y,是否存在一对完全不同的路径。

Input

第一行3个整数:n, m, z (2<=n<=100000, 1<=m,z<=100000),分别代表:n个岔口,m条边,事件数z。岔口编号为1~n。

下面m行:ai, bi (1<=ai,bi<= n, ai!=bi),描述一条边

然后下面z行描述事件:ti, ci, di (t=‘Z‘ or ‘P‘, 1<=ci,di<=n, ci!=di)。事件按照时间排序。

  • t=‘Z‘,表示删除一条边(ci, di),保证这条边之前没有被删除。注意,边可以被全部删除!
  • t=‘P‘,询问是否存在从ci到di的一对完全不同的路径。

Output

对于每组询问,如果存在,输出TAK,否则输出NIE

逆着操作顺序加边,同时并查集维护连通性和边双连通分量
预处理出按加边顺序得到的生成森林,在上面把每个连通块定向为有根树并标上深度
正式加边时,若两侧不连通则标为联通,否则将边的两端在生成树上的路径并成同一个边双连通分量
查询时可以直接判断两点是否在同个边双连通分量内

#include<bits/stdc++.h>
char buf[5000000],*ptr=buf-1;
int _(){
    int x=0,c=*++ptr;
    while(c<48)c=*++ptr;
    while(c>47)x=x*10+c-48,c=*++ptr;
    return x;
}
int _o(){
    int c=*++ptr;
    while(c<‘A‘||c>‘Z‘)c=*++ptr;
    return c;
}
const int N=100007;
int es[N*2],enx[N*2],ev[N*2],e0[N],ep=2,del[N];
int n,m,q,qs[N][3],f1[N],f2[N],fa[N],ap=0,dep[N];
bool ed[N],as[N];
int get(int*f,int x){
    int a=x,c;
    while(x!=f[x])x=f[x];
    while(x!=f[a])c=f[a],f[a]=x,a=c;
    return x;
}
struct edge{
    int a,b,id;
    bool operator<(edge e)const{return a!=e.a?a<e.a:b<e.b;}
    void chk(){
        int x=get(f1,a),y=get(f1,b);
        if(x!=y){
            f1[x]=y;
            ev[id<<1]=ev[id<<1|1]=1;
        }
    }
    void ins(){
        int x=get(f1,a),y=get(f1,b);
        if(x!=y){
            f1[x]=y;
            return;
        }
        a=get(f2,a);b=get(f2,b);
        while(a!=b){
            if(dep[a]<dep[b])b=f2[b]=get(f2,fa[b]);
            else a=f2[a]=get(f2,fa[a]);
        }
    }
}e[N];
void dfs(int w){
    ed[w]=1;
    for(int i=e0[w];i;i=enx[i]){
        int u=es[i];
        if(!ed[u]&&ev[i])fa[u]=w,dep[u]=dep[w]+1,dfs(u);
    }
}
void ae(){
    int a=_(),b=_();
    if(a>b)std::swap(a,b);
    e[ep>>1]=(edge){a,b,ep>>1};
    es[ep]=b;enx[ep]=e0[a];e0[a]=ep++;
    es[ep]=a;enx[ep]=e0[b];e0[b]=ep++;
}
void query(int a,int b){
    as[ap++]=(get(f2,a)==get(f2,b));
}
int main(){
    fread(buf,1,sizeof(buf),stdin);
    n=_();m=_();q=_();
    for(int i=1;i<=m;++i)ae();
    std::sort(e+1,e+m+1);
    for(int i=1,a,b;i<=q;++i){
        if(qs[i][0]=(_o()==‘Z‘)){
            a=_();b=_();
            if(a>b)std::swap(a,b);
            a=std::lower_bound(e+1,e+m+1,(edge){a,b})-e;
            ++del[a];
            qs[i][1]=a;
        }else{
            qs[i][1]=_();
            qs[i][2]=_();
        }
    }
    for(int i=1;i<=n;++i)f1[i]=i;
    for(int i=1;i<=m;++i){
        while(del[i])i+=del[i];
        if(i<=m)e[i].chk();
    }
    for(int i=q;i;--i)if(qs[i][0])e[qs[i][1]].chk();
    for(int i=1;i<=n;++i)if(!ed[i])dfs(i);
    for(int i=1;i<=n;++i)f1[i]=f2[i]=i;
    for(int i=1;i<=m;++i){
        while(del[i])i+=del[i];
        if(i<=m)e[i].ins();
    }
    for(int i=q;i;--i)if(qs[i][0])e[qs[i][1]].ins();else query(qs[i][1],qs[i][2]);
    while(ap)puts(as[--ap]?"TAK":"NIE");
    return 0;
}
时间: 2024-10-09 20:57:50

3069: [Pa2011]Hard Choice 艰难的选择的相关文章

BZOJ3069 : [Pa2011]Hard Choice 艰难的选择

在每条边两个点中间加上一个虚拟点代表这条边权,就可以化边权为点权. 把没删掉的边用LCT维护一棵生成树,树边都是桥. 对于一条非树边,把树上对应路径上所有边的权值都修改为0,表示都不是桥. 然后倒着处理询问,对于每次删掉的边,把两点路径上边权都修改为0. 询问等价于查询两点间边权和,若两点连通且路径上不存在桥,则有解. #include<cstdio> #include<map> const int N=200010,BUF=5000000; char Buf[BUF],*buf=

UVA 1175 Ladies&#39; Choice 女士的选择(稳定婚姻问题,GS算法)

题意: 给出每个男的心目中的女神排序,给出每个女的心目中的男神排序,即两个n*n的矩阵,一旦任意两个非舞伴的男女同学觉得对方都比现任舞伴要好,他们就会抛弃舞伴而在一起.为了杜绝这种现象,求每个男的最后所搭配的女伴是谁. 思路: 怎么感觉题意有点问题,输出的是第i行的男人所搭配的女人,即输出的是女人! 每个男人依次选择最喜欢的女人求婚,若同一个女的没人抢,则临时抢亲成功,若需要抢,明显女的都是喜欢挑长腿oba啦,矮冬瓜自动加入单身狗队列继续求婚!当单身狗所求的女神已订婚,只要女神更爱单身狗,没有什

JZOJ 3913. 艰难的选择

题目 Description Yzx已经当过多次“媒人”了.他因此获得了许多经验.例如,距Yzx观察,身高相近的人似乎比较合得来.Yzx在学校策划了一次大型的“非常男女”配对活动.对于这次活动的参与者,Yzx有自己独特的选择方式.他希望能选择男女人数相等且身高都很接近的一些人.这种选择方式实现起来很简单,他让学校的所有人按照身高排成一排,然后从中选出连续的若干个人,使得这些人中男女人数相等.Yzx当然希望他能选出的人越多越好,请告诉他最多可以选出多少人来. Input 第一行有一个正整数n,代表

选择&mdash;&mdash;ERP信息系统选型

做一次选择并不难,难的是做一次坚定而正确的选择.TCL电脑公司的ERP软件选型就是一次正确而艰难的选择过程.让我们从头说起吧!­ 业界都知道TCL电脑是IT行业的新入行者,更知道TCL的另一个诠释:"Today China Lion".而我们,作为TCL电脑人,在将精彩留给别人时,也不得不开始对我们自己及我们的生存环境进行反省与思考:我们一边要接受前方销售将士频频货源告急的抱怨,一边又要面临PC原材料更新换代造成的库存压力:我们一面要接受IT行业前所未有的变化速度与产品更替,一面是传统

python random 从集合中随机选择元素

使用python random模块的choice方法随机选择某个元素 from random import choice foo = ['a', 'b', 'c', 'd', 'e'] print (choice(foo)) 使用python random模块的sample函数从列表中随机选择一组元素 list = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] slice = random.sample(list, 5) #从list中随机获取5个元素,作为一个片断返回 pri

cong

Directions:  Study the following cartoon carefully and write an essay in which you should 1) describe the cartoon, 2) interpret its meaning, and 3) point out its implications in our life. You should write about 160—200 words neatly on ANSWER SH

tcp协议分析

tcp协议解析 TCP在网络OSI的七层模型中的第四层--Transport层,IP在第三层--Network层,ARP在第二层--Data Link层.在第二层上的数据,我们叫Frame,在第三层上的数据叫Packet,第四层的数据叫Segment. 我们程序的数据首先会打到TCP的Segment中,然后TCP的Segment会打到IP的Packet中,然后再打到以太网Ethernet的Frame中,传到对端后,各个层解析自己的协议,然后把数据交给更高层的协议处理 TCP头格式 TCP数据段格

谈谈对CAP定理的理解

谈谈对CAP定理的理解 CAP定理的常规解释是任何分布式系统只能在一致性(Consitency),可用性(Availability)和分区容忍性(Partition Tolerance)中三选二.这个解释很让人费解,笔者在看了一些文章后谈谈我对它的理解,还请斧正. 从问题出发 假设我们用一台服务器A对外提供存储服务,为了避免这台服务器宕机导致服务不可用,我们又在另外一台服务器B上运行了同样的存储服务.每次用户在往服务器A写入数据的时候,A都往服务器B上写一份,然后再返回客户端.一切都运行得很好,

TCP 的那些事儿(上)

http://coolshell.cn/articles/11564.html TCP是一个巨复杂的协议,因为他要解决很多问题,而这些问题又带出了很多子问题和阴暗面.所以学习TCP本身是个比较痛苦的过程,但对于学习的过程却能让人有很多收获.关于TCP这个协议的细节,我还是推荐你去看W.Richard Stevens的<TCP/IP 详解 卷1:协议>(当然,你也可以去读一下RFC793以及后面N多的RFC).另外,本文我会使用英文术语,这样方便你通过这些英文关键词来查找相关的技术文档. 之所以