Central Europe Regional Contest 2019 J. Saba1000kg (并查集+根号讨论)

链接:https://ac.nowcoder.com/acm/contest/7817/I
来源:牛客网

时间限制:C/C++ 2秒,其他语言4秒
空间限制:C/C++ 262144K,其他语言524288K
64bit IO Format: %lld

题目描述

There are many different streams in Viking rock movement. Old Icelandic granite rock, Mid- dle Danish dusty Viking rock, Late Finngail dark green rock, Fjord boulder avalanche rock, and many others, a complete list of all popular streams would overflow this page many times. The Scandinavian Ministry of Higher Education studies various ways the streams influence each other. They are currently planning a huge experiment, when a number of suitably chosen vol- unteers will be distributed over an archipelago of uninhabited small islands, and the researchers want to observe the mutual influence of their rock styles and preferences over a relatively long period of time. 

The inhabitants on one island will always influence each other. Some pairs of the islands are situated close enough for their inhabitants to influence each other, while the distances between other pairs prevent any direct influence. In the latter case, the inhabitants of such islands may still influence each other, but only indirectly, if there are one or more other islands that are inhabited and relay the influence. 

There are several proposals on the distribution of the volunteers among the islands. For each of these distributions, the Ministry would like to know the number of independent groups of inhab- itants that will form in the archipelago. Two groups of island inhabitants, each occupying one or more islands, are considered independent, if there is no possibility of their mutual influence, not even in the indirect way. 

Help the Ministry to evaluate their proposals.

输入描述:

The first input line contains three integers, N, E, P (1 ≤ N ≤ 10 5 ,0 ≤ E ≤ 10 5 ,1 ≤ P ≤ 10 5 ).
N is the number of islands in the archipelago, E is the number of pairs of islands that allow direct influence, and P is the number of proposals to be evaluated. The islands are labeled from 1 to N.

The next E lines specify the pairs of islands that allow direct mutual influence. Each of these lines contains two integers A and B denoting the labels of two different islands. No pair of islands occurs more than once.
Each of the next P lines describes one proposal. Each line starts with a number of islands inhabited under that proposal M (1 ≤ M ≤ N) and then contains pairwise distinct labels of M inhabited islands. No other island will be inhabited under the respective proposal.
The sum of the sizes of all proposals (all numbers M) does not exceed 10 5 .

输出描述:

For each proposal, print a line with the number of independent groups that will form in the archipelago.

示例1

输入

4 4 3
1 2
3 1
1 4
3 4
3 2 3 4
1 1
4 1 2 3 4

输出

2
1
1

示例2

输入

5 1 1
1 2
5 5 4 3 2 1

输出

4

题意:给定n个点m条无向边的图(n,m<=1e5),q次查询(q<=1e5),每次查询m个点,求查询的这m个点构成子图形成的连通块个数。保证q次查询的∑m≤1e5。

思路:按照度数是否小于sqrt(n)把点分为两类,度数小于sqrt(n)的点直接访问其所有邻接点,将其中正在查询的点与该点用并查集维护连通性。度数大于等于sqrt(n)的点先存到另一个集合里,然后互相查询这些点之间有没有边(这里可以用set,虽然多一个log但是跑的还算快),有的话就用并查集维护连通性。

按照这样分类讨论之后,由于q次查询,每次度数大于等于sqrt(n)的点有x个,那么最多有1e5/x个这样的查询,总复杂度不超过nsqrt(n)。

需要注意的是姿势不好会被卡常。

代码:

#include<bits/stdc++.h>
#define ll long long
#define inf 0x3f3f3f3f
#define rep(i,a,b) for(int i=(a);i<=(b);i++)
#define dep(i,a,b) for(int i=(a);i>=(b);i--)
#define ls (rt<<1)
#define rs (rt<<1|1)
#define B 400
using namespace std;
const int maxn=4e5+5;
//const double pi=acos(-1.0);
//const double eps=1e-9;
//const ll mo=1e9+7;
int n,m,k,q;
int a[maxn], c[maxn], du[maxn];
int ans,tmp,cnt;
int flag;
char s[maxn];
bool ok[maxn];
template <typename T>
inline void read(T &X){
    X=0;int w=0; char ch=0;
    while(!isdigit(ch)) {w|=ch=='-';ch=getchar();}
    while(isdigit(ch)) X=(X<<3)+(X<<1)+(ch^48),ch=getchar();
    if(w) X=-X;
}
int fa[maxn];
int find(int x) { return fa[x] == x ? x : fa[x] = find(fa[x]); }
void un(int x,int y){
    x = find(x);
    y = find(y);
    if(x==y)
        return;
    fa[y] = x;
}
vector<int> vc[maxn];
set<int> st[maxn];
int v[maxn], vv[maxn];
void solve(){
    //cout << sqrt(100000) << endl;
    read(n);
    read(m);
    read(q);
    rep(i,1,m){
        int u,v;
        read(u);
        read(v);
        vc[u].push_back(v);
        vc[v].push_back(u);
        du[u]++;
        du[v]++;
    }
    rep(i,1,n) {
        fa[i] = i;
        if(du[i]>=B){
            c[i] = 1;
            for(auto x : vc[i]){
                st[i].insert(x);
            }
        }
    }
    rep(i,1,q){
        v[0] = 0;
        vv[0] = 0;
        int sum;
        read(sum);
        rep(i,1,sum){
            int x;
            read(x);
            v[++v[0]] = x;
            a[x] = 1;
        }
        rep(t,1,v[0]){
            int x = v[t];
            if(!c[x]){
                for(auto y:vc[x]) if(a[y]){
                        un(x, y);
                }
            }
            else
                vv[++vv[0]] = x;
        }
        rep(xx,1,vv[0]){
            int x = vv[xx];
            rep(yy,xx+1,vv[0]) if(st[x].count(vv[yy])){
                int y = vv[yy];
                un(x, y);
            }
        }
        int ans = 0;
        rep(t,1,v[0]){
            int x = v[t];
            if(fa[x]==x)
                ans++;
        }
        printf("%d\n",ans);
        rep(t,1,v[0]){
            int x = v[t];
            fa[x] = x;
            a[x] = 0;
        }
    }
}
int main(){
/*
#ifdef ONLINE_JUDGE
#else
    freopen("D:/Temp/in.txt", "r", stdin);
#endif
*/
    // freopen("e://duipai//myout.txt","w",stdout);
    int T=1,cas=1;
    //read(T);
    while(T--){
        solve();
    }
    system("pause");
    return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值