【JZOJ A組】聽我說,海蝸牛
阿新 • • 發佈:2019-02-17
Description
Input
Output
Sample Input
4 4 3
1 4
1 2
1 3
2 3
4
1 2 3 4
3
1 2 3
2
1 2
Sample Output
2
3
2
Data Constraint
思路
正解就是爆搜!我比賽忘記判反向邊了
首先,想存下所有邊是不可能的,所以只能存被刪去的邊。
然後bfs時,用二分判斷這條邊是否相連。
但是,我們發現每搜一個點,就要詢問所有點是否相連或是否已去過,是O(ki^2)複雜度,只要資料極限就炸了!所以要用巧妙的方法來存沒到達的點。
我是開兩個佇列,每搜到一個點遍歷一遍佇列Q,如果那兩點之間的邊被刪了,就加入佇列q。結束時再把佇列q裡面的元素加入佇列Q。
程式碼
#include<iostream> #include<cstdio> #include<cstring> #include<vector> #include<algorithm> #include<queue> using namespace std; const int maxn=3e5+77; struct E { int x,y; }e[maxn]; int b[maxn],b1[maxn],n,m,t,cnt=0; vector<int> a[maxn]; queue<int> Q; bool cmp(E x,E y) { return (x.x<y.x)||(x.x==y.x&&x.y<y.y); } int find(int p,int x) { int l=0,r=a[p].size()-1; if(l>r) return 0x3f3f3f3f; while(l<=r) { if(l==r) return a[p][l]; int mid=(l+r)>>1; if(a[p][mid]>x) r=mid-1;else if(a[p][mid]<x) l=mid+1;else if(a[p][mid]==x) return a[p][mid]; } return a[p][l]; } void bfs(int x) { queue<int> qq,q; while(!qq.empty()) qq.pop(); while(!q.empty()) q.pop(); 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 u=q.front(); q.pop(); Q.push(u); } } } int main() { freopen("connect.in","r",stdin); freopen("connect.out","w",stdout); scanf("%d%d%d",&n,&m,&t); for(int i=1; i<=m; i++) { cnt++; scanf("%d%d",&e[cnt].x,&e[cnt].y); cnt++; e[cnt].x=e[cnt-1].y; e[cnt].y=e[cnt-1].x; } sort(e+1,e+cnt+1,cmp); for(int i=1; i<=cnt; i++) a[e[i].x].push_back(e[i].y); while(t--) { int k,ans=0; scanf("%d",&k); while(!Q.empty()) Q.pop(); for(int i=1; i<=k; i++) { int p; scanf("%d",&p); Q.push(p); } while(!Q.empty()) { int u=Q.front(); Q.pop(); bfs(u); ans++; } printf("%d\n",ans); } }