L2-025 分而治之

这题不多讲了,几乎是和前面的一题几乎一模一样,只有几点需要注意的地方
-
这题每检测玩一个方案之后要重置lost数组,为了方便,可以同时把vis数组的重置放在一起
-
检测的原理是:由于最后的城市都是孤立无援的,所以这时候的连通块数量是 总城市数 \(-\) 沦陷城市数
这里我刚开始把lost数组也放进了cnt函数里,结果当然是错误,因为所有输入的lost又被重置了。
不过我这里的代码与柳婼大大的是不一样的
但是她的思想值得介绍一下,对于一个城市,孤立无援一意味着每条边都是断的,即向左也不是,向右又不是。
她使用了一个结构体来存每条边,结构体里存的是两个端点(城市编号),还要用一个表来标记沦陷城市的编号,后续遍历的时候,如果一条边,有一端没有沦陷, 即它的状态还是false,就记录bool变量为false,说明这个方案失败。
想看柳婼代码的点这里
但是我还是觉得我的代码会更好,既是对前面的题目的一个巩固,又是对变化的适应。
但是,我的代码很显然是要慢很多的(实则就20,30ms),因为这道题的数据大起来了。另外值得一提的是这题时间特别宽松,如果加速,能降低到40ms速度,总之,这道题是很友好的一道题
#include<iostream>
#include<algorithm>
#include<vector>
#include<cstring>
using namespace std;
vector<int> a[10010];
bool lost[10010];
bool vis[10010];
int n,m;
void dfs(int u)
{
vis[u] = true;
for(auto v : a[u])
{
if(!lost[v] && !vis[v])
{
dfs(v);
}
}
}
int cnt()
{
int res = 0;
for(int i = 1 ; i <= n ; i ++)
{
if(!lost[i] && !vis[i])
{
res ++;
dfs(i);
}
}
return res;
}
int main()
{
cin>>n>>m;
while(m--)
{
int l,r;cin>>l>>r;
a[l].push_back(r);
a[r].push_back(l);
}
int k;cin>>k;
while(k--)
{
int t;cin>>t;
for(int i = 0 ; i < t ; i ++)
{
int x;cin>>x;
lost[x] = true;
}
int cnt1 = cnt();
if(cnt1 == n - t) cout<<"YES"<<endl;
else cout<<"NO"<<endl;
memset(lost,false,sizeof lost);
memset(vis,false,sizeof vis);
}
return 0;
}

浙公网安备 33010602011771号