判断图的连通性

来源:互联网 发布:学广东话软件 编辑:程序博客网 时间:2024/04/20 03:30

题目描述
给定一个无向图G,写一个程序处理以下两种操作:
1. 删去一条边(u, v)
2. 询问两点u,v 是否连通
输入
输入文件的第一行包含三个整数n, m, q,依次代表图的顶点数、边数、询问的个数。
接下来m 行,每行两个整数u, v,描述图中的一条边(u; v)。接下来q 行,每行三个整数t, u, v,描述一个操作。若t = 1 则操作代表删去边(u; v),否则操作代表询问点u 和v 是否连通。数据保证删除的边一定存在。

输出
对于每个询问操作输出一行字符串“Yes”(连通)或者“No”(不连通)。

样例输入
3 2 4
1 2
2 3
2 1 2
1 1 2
2 1 3
2 2 3
样例输出
Yes
No
Yes
提示
40%数据, n<=100, m<=1000, q<=1000
100%数据, n <=1000, m <= 100000, q <= 100000,可能存在重边。

并查集+逆向思维

考试的时候写了个广搜,觉得会超时,结果运行错误,只拿了30,让我百思不得其解。回家检查代码,结果发现打错了两个字母。。。(第一次这么手贱)其实不打错的话有80。。。
这题只要反着想就很简单了,先把所有边删光,把q个信息都储存下来离线操作。然后倒着来,是1就把两个端点并起来,是2就判断是否在同一集合中,用并查集维护连通性。

#include<cstdio>#include<iostream>#include<cstring>using namespace std;int n,m,q,x,y,u,v,len;int a[100005],b[100005],c[100005];int du[1005][1005],f[1005];char ans[100005][5];int get(int x){    if(f[x]==x) return x;else return f[x]=get(f[x]);}int main(){    cin>>n>>m>>q;    for(int i=1;i<=m;i++)     {        scanf("%d%d",&x,&y);        du[x][y]++;        du[y][x]++;    }    for(int i=1;i<=q;i++)     {        scanf("%d%d%d",&a[i],&b[i],&c[i]);        if(a[i]==1)         {            du[b[i]][c[i]]--;            du[c[i]][b[i]]--;        }    }    for(int i=1;i<=n;i++) f[i]=i;    for(int i=1;i<=n;i++)     for(int j=1;j<=n;j++)     if(du[i][j]>0)     {        u=get(i);        v=get(j);        f[v]=u;    }    for(int i=q;i>=1;i--)     if(a[i]==1)     {        u=get(b[i]);        v=get(c[i]);        f[v]=u;    }    else    {        u=get(b[i]);        v=get(c[i]);        if(u!=v)         {            len++;            strcpy(ans[len],"No");        }        else        {            len++;            strcpy(ans[len],"Yes");        }    }    for(int i=len;i>=1;i--) printf("%s\n",ans[i]);    return 0;}

以后顺着做做不出,一定要想想能不能离线操作或倒着来!
正难则反,切记切记!

0 0
原创粉丝点击