點擊打開鏈接
注意到20w條邊,但是詢問只有1w,所以有很多邊是從頭到尾不變的。
首先離線處理,將從未刪除的邊縮點,縮點後的圖的點數不會超過2w,對於每一次add或者delete,直接dfs看是否能從a走到b,然後維護一個ans。
數據不強,不然這種復雜度起碼要跑10s。。
#include#include #include #include using namespace std; #define N 5001 #define M 530005 struct node2 { char q; int a,b; }f[200005],Q[10005]; struct node { int v,next; }edge[M]; int head[N],set[N]; bool d[N][N],v[N]; int e[N][N]; int id,ans; void add(int a,int b) { edge[id].v=b; edge[id].next=head[a]; head[a]=id++; } void init(int n) { memset(head,-1,sizeof(head)); id=ans=0; for(int i=1;i<=n;i++)set[i]=i; } int find(int x) { if(x!=set[x]) return set[x]=find(set[x]); return set[x]; } void merge(int x,int y) { set[find(y)]=find(x); } bool dfs(int a,int b) { if(a==b) return true; for(int i=head[a];~i;i=edge[i].next) { int to=edge[i].v; if(e[a][to]>0&&!v[to]) { v[to]=true; if(dfs(to,b)) return true; } } return false; } int n; void addedge(int a,int b) { memset(v,false,sizeof(v)); if(!dfs(a,b)) ans--; e[a][b]++; e[b][a]++; add(a,b); add(b,a); } void del(int a,int b) { memset(v,false,sizeof(v)); e[a][b]--; e[b][a]--; if(!dfs(a,b)) ans++; } inline int ReadInt() { char ch = getchar(); int data = 0; while (ch < '0' || ch > '9') { ch = getchar(); } do { data = data*10 + ch-'0'; ch = getchar(); }while (ch >= '0' && ch <= '9'); return data; } int main() { int m,a,b,q; n=ReadInt(); m=ReadInt(); init(n); for(int i=1;i<=m;i++) { f[i].a=ReadInt(); f[i].b=ReadInt(); } q=ReadInt(); for(int i=1;i<=q;i++) { scanf("%s",&Q[i].q); if(Q[i].q!='Q') { Q[i].a=ReadInt(); Q[i].b=ReadInt(); if(Q[i].q=='D') d[Q[i].a][Q[i].b]=d[Q[i].b][Q[i].a]=true; } } for(int i=1;i<=m;i++) { if(!d[f[i].a][f[i].b]) merge(f[i].a,f[i].b); } for(int i=1;i<=n;i++) { if((set[i]=find(i))==i) ans++; } for(int i=1;i<=m;i++) { if(set[f[i].a]!=set[f[i].b]) addedge(set[f[i].a],set[f[i].b]); } for(int i=1;i<=q;i++) { if(Q[i].q=='Q') printf("%d\n",ans); else if(Q[i].q=='D') del(set[Q[i].a],set[Q[i].b]); else addedge(set[Q[i].a],set[Q[i].b]); } return 0; }