【NOIP模拟题】连通

Overview

给定一个无向图,请编写一个程序实现以下两种操作:
(1)D x y,从原图中删除连接x和y顶点的边。
(2)Q x y,询问x和y顶点是否连通。

Analysis

这也是连通问题,考虑用并查集解决。
但是这是删除的问题耶,怎么办?
考虑将删除变为连通,能不能将所有操作给反过来,从最后一个操作开始处理。
当然是可以的。

Code

#include <bits/stdc++.h>
using namespace std;

typedef long long Lint;
const int N=161240*4;
const int MOD=100009;

int n,q;
int f[N];
char kind[N]; int cx[N],cy[N];

inline int read(void)
{
    int s=0; char c=getchar();
    for (;!isdigit(c);c=getchar());
    for (;isdigit(c);c=getchar()) s=s*10+c-'0';
    return s;
}

int m;
int ed[N][2];
struct Hash
{
    int u,v,nxt;
}h[N<<1];
int tt,hd[MOD];

int find(int i)
{
    return f[i]==i?i:f[i]=find(f[i]);
}

inline void ins(int u,int v)
{
    int key=((Lint)u*n+v)%MOD;
    h[++tt].u=u;
    h[tt].v=v;
    h[tt].nxt=hd[key];
    hd[key]=tt;
}

inline int del(int u,int v)
{
    int key=((Lint)u*n+v)%MOD;
    for (int k=hd[key];k;k=h[k].nxt) if (h[k].u==u&&h[k].v==v) return 1;
    return 0;
}

void init(void)
{
    n=read(),m=read();
    for (int i=1;i<=n;i++) f[i]=i;
    for (int i=1;i<=m;i++) ed[i][0]=read(),ed[i][1]=read();
    q=read();
    for (int i=1;i<=q;i++)
    {
        scanf("\n"),kind[i]=getchar();
        cx[i]=read(),cy[i]=read();
        if (kind[i]=='D') ins(cx[i],cy[i]),ins(cy[i],cx[i]);
    }
    for (int i=1;i<=m;i++) 
        if (!del(ed[i][0],ed[i][1]))
            f[find(ed[i][0])]=find(ed[i][1]);
}

int res[N];

void work(void)
{
    for (int i=q;i>=1;i--) kind[i]=='D'?f[find(cx[i])]=find(cy[i]):res[++res[0]]=find(cx[i])==find(cy[i]);
    for (int i=res[0];i>0;i--) printf("%c\n",res[i]?'C':'D');
}

int main(void)
{
    init();
    work();
    return 0;
}

Sumarize

多次操作的离线算法有以下2种:
①结合各种定序和存储方法,在遍历其他的时候顺便求解。
②得到最后一次的答案,反向推回来。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值