[BFS][链表][二分][STL]JZOJ 5875 听我说,海蜗牛
分析
这题我们可以用一个链表来搞未加入连通块的点,然后在一个vector里面二分找当前点是否被断边(其实最好用哈希)
然后就裸搜了
听从大佬王的建议用两条队列写了链表(我傻了?)
#pragma GCC optimize(2) #include <iostream> #include <cstdio> #include <vector> #include <queue> #include <algorithm> using namespace std; const int N=2e5+10; struct Edge { int u,v; }e[2*N]; int cnt; int n,m,q; vector<int> a[N/2]; queue<int> qv; bool Cmp(Edge a,Edge b) { return a.v<b.v; } int Find(int p,int x) { int l=0,r=a[p].size()-1; if (r<l) return 2147483647; while (l<=r) { int mid=l+r>>1; if (a[p][mid]==x) return a[p][mid]; if (a[p][mid]>x) r=mid-1; else l=mid+1; } return a[p][l]; } void Bfs(int v0) { queue<int> qu,q; while (!qu.empty()) qu.pop(); while (!q.empty()) q.pop(); qu.push(v0); while (!qu.empty()) { int u=qu.front();qu.pop(); while (!qv.empty()) { int v=qv.front();qv.pop(); if (Find(u,v)!=v) qu.push(v); else q.push(v); } while (!q.empty()) { int p=q.front();q.pop(); qv.push(p); } } } int main() { freopen("connect.in","r",stdin); freopen("connect.out","w",stdout); scanf("%d%d%d",&n,&m,&q); for (int i=1;i<=m;i++) { cnt++; scanf("%d%d",&e[cnt].u,&e[cnt].v); e[++cnt].u=e[cnt-1].v;e[cnt].v=e[cnt-1].u; } sort(e+1,e+cnt+1,Cmp); for (int i=1;i<=cnt;i++) a[e[i].u].push_back(e[i].v); for (int i=1;i<=q;i++) { int p; scanf("%d",&p); while (!qv.empty()) qv.pop(); for (int j=1;j<=p;j++) { int x; scanf("%d",&x); qv.push(x); } int ans=0; while (!qv.empty()) { int u=qv.front();qv.pop(); Bfs(u); ans++; } printf("%d\n",ans); } fclose(stdin);fclose(stdout); }
在日渐沉没的世界里,我发现了你。