L2-025 分而治之 (25分) C++

    科技2022-07-13  136

    题目描述

    分而治之,各个击破是兵家常用的策略之一。在战争中,我们希望首先攻下敌方的部分城市,使其剩余的城市变成孤立无援,然后再分头各个击破。为此参谋部提供了若干打击方案。本题就请你编写程序,判断每个方案的可行性。

    输入格式:

    输入在第一行给出两个正整数 N 和 M(均不超过10 000),分别为敌方城市个数(于是默认城市从 1 到 N 编号)和连接两城市的通路条数。随后 M 行,每行给出一条通路所连接的两个城市的编号,其间以一个空格分隔。在城市信息之后给出参谋部的系列方案,即一个正整数 K (≤ 100)和随后的 K 行方案,每行按以下格式给出:

    Np v[1] v[2] … v[Np] 其中 Np 是该方案中计划攻下的城市数量,后面的系列 v[i] 是计划攻下的城市编号。

    输出格式:

    对每一套方案,如果可行就输出YES,否则输出NO。

    输入样例

    10 11 8 7 6 8 4 5 8 4 8 1 1 2 1 4 9 8 9 1 1 10 2 4 5 4 10 3 8 4 6 6 1 7 5 4 9 3 1 8 4 2 2 8 7 9 8 7 6 5 4 2

    输出样例

    NO YES YES NO NO

    分析

    图论基本做法,最后检验连通性即可。 连通性检验:用set把需要被攻占的城市加入,然后对没有攻占的城市查询是否有与其相连的城市,若有则表明城市有相连,输出"NO",反之则输出"YES"

    C++ 代码

    #include<bits/stdc++.h> using namespace std; const int N = 1e4+10; int n,m; int h[N],e[2*N],ne[2*N],idx; void add(int a,int b) { e[idx]=b,ne[idx]=h[a],h[a]=idx++; } int main() { memset(h,-1,sizeof h); scanf("%d%d",&n,&m); int a,b; for(int i=0;i<m;i++) { scanf("%d%d",&a,&b); add(a,b); add(b,a); } int k; scanf("%d",&k); while(k--) { set<int> s; int np,point; scanf("%d",&np); for(int i=0;i<np;i++) { scanf("%d",&point); s.insert(point); //将攻占的城市加入集合 } int f=0; for(int i=1;i<=n;i++) { if(!s.count(i)) { for(int j=h[i];j!=-1;j=ne[j]) //检验没有被攻占的城市的连通性 { int t=e[j]; if(!s.count(t)) { puts("NO"); f=1; break; } } } if(f==1) break; } if(f==0) puts("YES"); } return 0; }
    Processed: 0.017, SQL: 8