1. 程式人生 > >BZOJ5218: [Lydsy2017省隊十連測]友好城市(kosaraju演算法)

BZOJ5218: [Lydsy2017省隊十連測]友好城市(kosaraju演算法)

傳送門

題解: 利用kosaraju+bitset可以在知道鄰接矩陣的情況下O(n232)O(\frac{n^2}{32})解決強連通分量計數。

用回滾莫隊即可在O(mm)O(m \sqrt{m})的時間內獲得所有詢問的鄰接矩陣了。 時間複雜度O(mm+qn232)O( m\sqrt{m} + q\frac{n^2}{32})

#include <bits/stdc++.h>
#include <bitset>
using namespace std;
typedef pair <int,int> pii;
const int RLEN=1<<18|1; inline char nc() { static char ibuf[RLEN],*ib,*ob; (ib==ob) && (ob=(ib=ibuf)+fread(ibuf,1,RLEN,stdin)); return (ib==ob) ? -1 : *ib++; } inline int rd() { char ch=nc(); int i=0,f=1; while(!isdigit(ch)) {if(ch=='-')f=-1; ch=nc();} while(isdigit(ch)) {i=(i<<
1)+(i<<3)+ch-'0'; ch=nc();} return i*f; } inline void W(int x) { static int buf[50]; if(!x) {putchar('0'); return;} if(x<0) {putchar('-'); x=-x;} while(x) {buf[++buf[0]]=x%10; x/=10;} while(buf[0]) {putchar(buf[buf[0]--]+'0');} } const int N=151, M=3e5+50, S=450; typedef bitset <N> bs; struct
data { int l,r,id; data(int l,int r,int id) : l(l),r(r),id(id) {} friend inline bool operator <(const data &a,const data &b) {return a.r<b.r;} }; int n,m,q,a[M],b[M],bg[M],ed[M],ans[M],h; bs ori[N],rev[N],t1[N],t2[N],vis; vector <data> qry[M/S+2][M/S+2]; int out[N],ind,res; inline void dfs(int x) { bs now; vis[x]=1; while((now=ori[x]^(ori[x]&vis)), now.any()) { int v=now._Find_first(); dfs(v); } out[++ind]=x; } inline int dfs_rev(int x) { int s=1; bs now; vis[x]=1; while((now=rev[x]^(rev[x]&vis)), now.any()) { int v=now._Find_first(); s+=dfs_rev(v); } return s; } inline int kosaraju() { vis.reset(); ind=0; for(int i=1;i<=n;i++) if(!vis[i]) dfs(i); vis.reset(); res=0; for(int i=n;i>=1;i--) if(!vis[out[i]]) { int x=dfs_rev(out[i]); res+=x*(x-1)/2; } return res; } inline void clear() {for(int i=1;i<=n;i++) ori[i].reset(), rev[i].reset();} inline void inc(int l,int r) { ori[l].set(r); rev[r].set(l); } inline void bf_solve(int l,int r,int id) { for(int i=l;i<=r;i++) inc(a[i],b[i]); ans[id]=kosaraju(); clear(); } int main() { n=rd(), m=rd(), q=rd(); for(int i=1;i<=m;i++) a[i]=rd(), b[i]=rd(); for(int l=1,r;l<=m;l=r+1) { r=min(l+S-1,m); bg[++h]=l; ed[h]=r; } for(int i=1;i<=q;i++) { int l=rd(), r=rd(); if(r-l+1<=2*S) bf_solve(l,r,i); else qry[(l-1)/S+2][r/S].push_back(data(l,r,i)); } for(int i=1;i<=h;i++) for(int j=i;j<=h;j++) sort(qry[i][j].begin(),qry[i][j].end()); for(int i=1;i<=h;i++) { int r=ed[i-1]; for(int j=i;j<=h;j++) { while(r<ed[j]) ++r, inc(a[r],b[r]); for(int z=0;z<qry[i][j].size();++z) { data &q=qry[i][j][z]; while(r<q.r) ++r, inc(a[r],b[r]); for(int i=1;i<=n;i++) t1[i]=ori[i], t2[i]=rev[i]; for(int t=bg[i]-1;t>=q.l;--t) inc(a[t],b[t]); ans[q.id]=kosaraju(); for(int i=1;i<=n;i++) ori[i]=t1[i], rev[i]=t2[i]; } } clear(); } for(int i=1;i<=q;i++) W(ans[i]), putchar('\n'); }