BZOJ5218: [Lydsy2017省隊十連測]友好城市(kosaraju演算法)
阿新 • • 發佈:2018-12-11
題解: 利用kosaraju+bitset可以在知道鄰接矩陣的情況下解決強連通分量計數。
用回滾莫隊即可在的時間內獲得所有詢問的鄰接矩陣了。 時間複雜度。
#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');
}