每日闲聊
攒了800多原石,在线等叶宝.
一命了啊,叶宝还是爱我的.
题目大意
给定一个图和 k k k次询问,每次询问给出 l , r l,r l,r,将编号在 [ l , r ] [l,r] [l,r]中的边去掉,问有几个连通块,询问完再将删去的边连回去.
给定数据
第一行为 n , m n,m n,m,表示 n n n个顶点和 m m m条边.
接下来有 m m m行,每行给出 a , b a,b a,b,表示 a , b a,b a,b之间的连边.
再给出 k k k.
最后有 k k k行,每行给出 l , r l,r l,r,表示断开编号在 [ l , r ] [l,r] [l,r]中的边.
输出要求
输出 k k k行,分别对应 k k k次询问中的连通块数量.
解题思路
暴力啊,直接DFS.
每次询问时不是有
l
,
r
l,r
l,r吗,读入的时候记录边的编号,在DFS的过程中判断一下即可.然后遍历
1
到
n
1到n
1到n的点,如果book[i]==0
,就以该点为起点DFS,同时++ans
,循环后输出ans
.
蒟蒻的AC代码
#include<bits/stdc++.h>
#define pii pair<int,int>
#define F first
#define S second
using namespace std;
const int N=5e2+5;
int n,m,k,a,b,ans;
bool book[N];
vector<pii> e[N];
void dfs(int cur,int l,int r){
book[cur]=1;
for(auto to:e[cur]){
if(l<=to.S && to.S<=r) continue;
if(!book[to.F]){
dfs(to.F,l,r);
}
}
}
int main(){
scanf("%d%d",&n,&m);
for(int i=1;i<=m;++i){
scanf("%d%d",&a,&b);
e[a].push_back({b,i});
e[b].push_back({a,i});
}
scanf("%d",&k);
while(k--){
scanf("%d%d",&a,&b);
ans=0;
memset(book,0,sizeof book);
for(int i=1;i<=n;++i){
if(!book[i]){
dfs(i,a,b);
++ans;
}
}
printf("%d\n",ans);
}
return 0;
}