专栏文章
题解:P11545 [Code+#5] 监控中心
P11545题解参与者 1已保存评论 0
文章操作
快速查看文章及其快照的属性,并进行相关操作。
- 当前评论
- 0 条
- 当前快照
- 1 份
- 快照标识符
- @miprw8m5
- 此快照首次捕获于
- 2025/12/03 16:56 3 个月前
- 此快照最后确认于
- 2025/12/03 16:56 3 个月前
题目大意
给定一个 个点 条边的无向图,对于 组测试数据输出不能与所有点联通的点的个数。
坑点
-
对于城市 和 不一定只有一个情报中心。
-
在遍历图的过程中可能会因递归堆栈过多爆空间。
-
有自己指向自己的边,需要筛掉(或者在计算答案的时候直接过滤掉)。
分析

因为样例太特殊,所以自己造了组样例,设 表示发出信号的点、 为被报告的点,下面来分析两种操作。
-
若 是 的儿子(因为 只能是 或 ,所以不需要并查集来找父亲,但需要考虑上文提到的 的情况),则只有 的子树(包括自己)符合条件。
-
若 是 的儿子,则 的子树都不符合条件。
看一组样例:
TXT7 6
1 2
1 3
2 4
2 5
3 6
3 7
3
3 -1 6 5
2 -1 -2
2 1 2
对于
3 -1 6 5 这组数据,答案应为 。对于
2 -1 -2 这组数据,显然只有 不行,所以答案为 。对于
2 1 2 这组数据,显然只有 行,所以答案为 。再看不懂就直接看代码吧:
CPP#include<bits/stdc++.h>
//#define int long long
#define endl "\n"
#define er puts("")
#define sc putchar(' ')
#define AzureLine return 0
using namespace std;
const int N=25e5+5;
int a[N],b[N],sz[N],fa[N];
vector<int>e[N];
void dfs(int x)
{
sz[x]=1;//子树算上自己
for(int i=0;i<e[x].size();i++)
{
int y=e[x][i];
if(fa[y]) continue; //双向边,记得continue
fa[y]=x;dfs(y);
sz[x]+=sz[y];
}
}
int read()
{
int x=0,a=1;char c=getchar();
for(;c<'0'||c>'9';c=getchar())
if(c=='-') a=-1;
for(;c>='0'&&c<='9';c=getchar())
x=x*10+c-'0';
return x*a;
}
void write(int x)
{
if(x<0) x*=-1,putchar('-');
if(x>9) write(x/10);
putchar(x%10+'0');
return;
}
signed main()
{
int n=read(),m=read();
for(int i=1;i<=m;i++)
{
a[i]=read(),b[i]=read();
e[a[i]].push_back(b[i]);
e[b[i]].push_back(a[i]);
}
fa[1]=-1;dfs(1);
// for(int i=1;i<=n;i++) write(sz[i]),sc;
int q=read();
while(q--)
{
int c=read(),ans=0;//多测清空
for(int i=1;i<=c;i++)
{
int x=read(),u,v;
if(x>0) u=a[x],v=b[x];
else u=b[-x],v=a[-x];
if(u==fa[v]) ans+=sz[v];
if(v==fa[u]) ans-=sz[u];
}
write(ans>=0?ans:ans+n),er;//如果ans为负,那显然是应为求的是合适的点,所以加n
}
return 0;
}
相关推荐
评论
共 0 条评论,欢迎与作者交流。
正在加载评论...