星星之火

[JZOJ 5875] [NOIP2018提高组模拟9.20] 听我说,海蜗牛 解题报告(BFS+二分)

题目链接:

http://172.16.0.132/senior/#main/show/5875

题目:

题解:

注意这题只能经过开放的港口

我们考虑用vector存下每个点不能到的点,并把并让vector里面的元素升序排序,这样我们就可以二分查找一个点是否与另外一个点相连

接下来我们对于每一个开放的港口bfs,每次bfs都把属于这个连通块的港口去掉

考虑开两个队列来bfs,队列1存储的是当前连通块里还没有拓展的点,队列2里存储的是还剩下的点,看看代码就可以理解了

#include<algorithm>
#include<cstring>
#include<cstdio>
#include<iostream>
#include<vector>
#include<queue>
using namespace std;

const int N=1e5+15;
int n,m,t;
struct E{
    int x,y;
}e[N<<2];
vector <int> p[N];
queue <int> Q;
inline int read(){
    char ch=getchar();int s=0,f=1;
    while (ch<'0'||ch>'9') {if (ch=='-') f=-1;ch=getchar();}
    while (ch>='0'&&ch<='9') {s=(s<<3)+(s<<1)+ch-'0';ch=getchar();}
    return s*f;
}
bool cmp(E a,E b){return a.x<b.x||(a.x==b.x&&a.y<b.y);}
int find(int u,int v){
    int l=0,r=p[u].size()-1;
    if (l>r) return -1;
    while (l<=r){
        if (l==r) return p[u][l];
        int mid=l+r>>1;
        if (p[u][mid]>v) r=mid-1;else 
        if (p[u][mid]<v) l=mid+1;else 
        if (p[u][mid]==v) return p[u][mid];
    }
    return p[u][l];
}
void bfs(int x){
    queue <int> qq,q;
    qq.push(x);
    while (!qq.empty())
    {
        int u=qq.front();qq.pop();
        while (!Q.empty()){
            int v=Q.front();Q.pop();
            if (find(u,v)!=v) qq.push(v);
            else q.push(v);
        }
        while (!q.empty()){
            int v=q.front();q.pop();
            Q.push(v);
        }
    }
}
int main(){
    freopen("connect.in","r",stdin);
    freopen("connect.out","w",stdout);
    n=read();m=read();t=read();
    int cnt=0;
    for (int i=1;i<=m;i++){
        ++cnt;
        e[cnt].x=read();e[cnt].y=read();
        ++cnt;
        e[cnt].x=e[cnt-1].y;e[cnt].y=e[cnt-1].x;
    }
    sort(e+1,e+1+cnt,cmp);
    for (int i=1;i<=cnt;i++) p[e[i].x].push_back(e[i].y);
    while (t--){
        int k=read(),ans=0;
        while (!Q.empty()) Q.pop();
        for (int i=1;i<=k;i++){
            int s=read();
            Q.push(s);
        }
        while (!Q.empty()){
            int s=Q.front();Q.pop();
            bfs(s);++ans;
        }
        printf("%d\n",ans);
    }  
    return 0;
}
posted @ 2018-10-17 19:27  星星之火OIer  阅读(235)  评论(0编辑  收藏  举报