题目链接:
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 ",ans); } return 0; }