嗯就如上一篇所说,我们缩完点之后,就成为了一棵树,然后每个点权对应它到他的父节点的边是否狗带,然后每次LCA在链上乱跳的时候维护下清空标记就行了,qlog^2n的果然跑得快,172ms。。。。。。
Problem: 3694 User: BPM136 Memory: 19208K Time: 172MS Language: G++ Result: Accepted Source Code /* *********************************************** Author :BPM136 Created Time :2016/5/6 22:20:26 File Name :A.cpp ************************************************ */ #include<iostream> #include<cstdio> #include<algorithm> #include<cstdlib> #include<cmath> #include<cstring> #define LL long long #define get(a,i) a&(1<<(i-1)) #define PAU putchar(32) #define ENT putchar(10) #define fo(_i,_a,_b) for(int _i=_a;_i<=_b;_i++) #define efo(_i,_a) for(int _i=last[_a];_i!=0;_i=e[_i].next) #define file(x) freopen(#x".in","r",stdin),freopen(#x".out","w",stdout); #define setlargestack(x) int size=x<<20;char *p=(char*)malloc(size)+size;__asm__("movl %0, %%esp\n" :: "r"(p)); using namespace std; LL read() { LL f=1,d=0;char s=getchar(); while (s<48||s>57){if (s==45) f=-1;s=getchar();} while (s>=48&&s<=57){d=d*10+s-48;s=getchar();} return f*d; } LL readln() { LL f=1,d=0;char s=getchar(); while (s<48||s>57){if (s==45) f=-1;s=getchar();} while (s>=48&&s<=57){d=d*10+s-48;s=getchar();} while (s!=10) s=getchar(); return f*d; } inline void write(LL x) { if(x==0){putchar(48);return;}if(x<0)putchar(45),x=-x; int len=0,buf[20];while(x)buf[len++]=x%10,x/=10; for(int i=len-1;i>=0;i--)putchar(buf[i]+48);return; } inline void writeln(LL x){write(x);ENT;} const int N = 100005; const int M = 200005; struct edge { int y,next; }ee[M*2],e[M*2]; int last1[N],ne1; int last[N],ne; #define efo1(i,x) for(int i=last1[x];i!=0;i=ee[i].next) int low[N],dfn[N],Dfn[N],fa[N],mark[N],f[N]; int sum[N<<2],lz[N<<2]; int siz[N],son[N],top[N],first[N],en[N],fat[N],ft[N],dep[N],nu; int B[M][2],Lb[N],Le[N],L[N],dl[N],Ln,bn; int n,m,ans,index; int find(int x) { if(f[x]==x) return x; return f[x]=find(f[x]); } int findt(int x) { if(ft[x]==x) return x; return ft[x]=findt(ft[x]); } void add(int x,int y) { ee[++ne1].y=y;ee[ne1].next=last1[x];last1[x]=ne1; } void add2(int x,int y) { add(x,y); add(y,x); } void addt(int x,int y) { e[++ne].y=y;e[ne].next=last[x];last[x]=ne; } void init() { memset(mark,0,sizeof(mark)); memset(low,0,sizeof(low)); memset(last1,0,sizeof(last1)); memset(last,0,sizeof(last)); memset(fat,0,sizeof(fat)); memset(dfn,0,sizeof(dfn)); ne=ne1=ans=index=nu=0; Ln=1; bn=0; fo(i,1,n)f[i]=i; fo(i,1,m) { int x=read(),y=read(); add2(x,y); } } void Tarjan(int x) { Dfn[x]=Dfn[fa[x]]+1; dfn[x]=low[x]=++index; efo1(i,x) { int y=ee[i].y; if(!dfn[y]) { fa[y]=x; Tarjan(y); low[x]=min(low[x],low[y]); if(low[y]>dfn[x]) { mark[y]=1; ans++; B[++bn][0]=x,B[bn][1]=y; }else f[find(x)]=find(y); }else if(fa[x]!=y) low[x]=min(low[x],dfn[y]); } } int root; void dfs1(int x,int de) { dep[x]=de;siz[x]=1;int mx=0,num=-1; efo(i,x) { int y=e[i].y; if(y==fat[x]) continue; fat[y]=x; dfs1(y,de+1); siz[x]+=siz[y]; if(siz[y]>mx) { mx=siz[y]; num=y; } } son[x]=num; } void dfs2(int x,int t) { first[x]=++nu,top[x]=t; if(son[x]>0)dfs2(son[x],t); else Le[dl[t]]=nu; efo(i,x) { int y=e[i].y; if(y==fat[x]||y==son[x])continue; fat[y]=x; dl[y]=++Ln; Lb[dl[y]]=nu+1; dfs2(y,y); //w[y]=1; } en[x]=nu; } #define lch (k<<1) #define rch (k<<1|1) void buildsegtree(int k,int l,int r) { if(l==r) { if(l!=1)sum[k]=1;else sum[k]=0; lz[k]=0; // cerr<<l<<' '<<r<<' '<<sum[k]<<endl; return ; } int mid=(l+r)>>1; buildsegtree(lch,l,mid); buildsegtree(rch,mid+1,r); sum[k]=sum[lch]+sum[rch]; lz[k]=0; // cerr<<l<<' '<<r<<' '<<sum[k]<<' '<<sum[lch]<<' '<<sum[rch]<<endl; } /* void insert(int k,int l,int r,int ll,int rr) { if(l==ll&&r==rr) { sum[k]=rr-ll; lz[k]=1; return ; } int mid=(l+r)>>1; if(rr<=mid)insert(lch,l,mid,ll,rr);else if(ll>mid)insert(rch,mid+1,r,ll,rr);else { insert(lch,l,mid,ll,mid); insert(rch,mid+1,r,mid+1,rr); } pushup(k); } */ void pushdown(int k) { /* if(lz[k]==1) { int mid=(l+r)>>1; lz[lch]=lz[rch]=1; sum[lch]=mid-l; sum[rch]=r-mid-1; }else if(lz[k]==2){ sum[lch]=sum[rch]=0; lz[lch]=lz[rch]=2; } */ sum[lch]=sum[rch]=0; lz[lch]=lz[rch]=1; lz[k]=0; } int ret1; int get_ans(int k,int l,int r,int _l,int _r) { if(l>r||_l>_r)return 0; if(l==_l&&r==_r) { ret1=sum[k]; sum[k]=0; lz[k]=1; return ret1; } if(lz[k])pushdown(k); int mid=(l+r)>>1; int ret=0; if(_r<=mid) ret=get_ans(lch,l,mid,_l,_r); else if(_l>mid) ret=get_ans(rch,mid+1,r,_l,_r); else { ret=get_ans(lch,l,mid,_l,mid)+get_ans(rch,mid+1,r,mid+1,_r); } // cout<<l<<' '<<r<<' '<<_l<<' '<<_r<<' '<<ret<<endl; sum[k]=sum[lch]+sum[rch]; return ret; } int lca,a,ret; void LCA(int x,int y) { while(1) { if(top[x]==top[y]) { lca=dep[x]<dep[y]?x:y, a=(x==lca)?y:x, ret=0; // cout<<"LCAarrive"<<first[lca]<<' '<<first[a]<<endl; if(lca!=a) ret=get_ans(1,1,nu,first[lca]+1,first[a]); // cout<<"LCA: "<<lca<<' '<<a<<' '<<first[lca]<<' '<<first[a]<<' '<<ret<<endl; ans-=ret; return; } if(dep[top[x]]<dep[top[y]]) { int ret=get_ans(1,1,nu,Lb[dl[top[y]]],first[y]); ans-=ret; y=fa[top[y]]; //if(w[y]) w[y]=0,ans--; } else { int ret=get_ans(1,1,nu,Lb[dl[top[x]]],first[x]); ans-=ret; x=fa[top[x]]; //if(w[x]) w[x]=0,ans--; } // cout<<x<<' '<<y<<' '<<top[x]<<' '<<top[y]<<endl; // cout<<dep[top[x]]<<' '<<dep[top[y]]<<endl; } } void checkt(int x,int pre) { cout<<pre<<' '<<x<<endl; efo(i,x) { int y=e[i].y; if(y!=pre) checkt(y,x); } } void work() { Tarjan(1); // cerr<<ans<<endl; // fo(i,1,n) tmp[i]=f[i]; // sort(tmp+1,tmp+n+1); // int tmpn=0;tmp[0]=-1; // fo(i,1,n) if(tmp[i]!=tmp[i-1]) tmp[++tmpn]=tmp[i]; fo(i,1,n)ft[i]=i; fo(i,1,bn) { int x=findt(B[i][0]),y=findt(B[i][1]); // cout<<"Bz::"<<B[i][0]<<' '<<B[i][1]<<endl; if(x!=y) { x=find(B[i][0]),y=find(B[i][1]); addt(x,y),addt(y,x),root=x; // cout<<"B:: "<<x<<' '<<y<<endl; ft[x]=y; } } // cout<<"Root::"<<root<<endl; // checkt(root,-1); // cout<<"finishcheck"<<endl; dfs1(root,1); Lb[1]=1; dl[root]=1; dfs2(root,root); // cout<<"Liannum:: "<<Ln<<endl; // cout<<Lb[1]<<' '<<Le[1]<<endl; // fo(i,1,n) cout<<first[i]<<' ';cout<<endl; // fo(i,1,n) cout<<en[i]<<' ';cout<<endl; // fo(i,1,n) cout<<top[i]<<' ';cout<<endl; buildsegtree(1,1,nu); // fo(i,1,Ln) insert(1,1,nu,Lb[i],Le[i]);//,cout<<Lb[i]<<' '<<Le[i]<<endl; int T=read(); while(T--) { int x=read(),y=read(); x=find(x),y=find(y); // cout<<x<<' '<<y<<' '<<T<<endl; if(x!=y)LCA(x,y); // cout<<"Wan?"<<endl; writeln(ans); } ENT; } int main() { int T = 0; while(scanf("%d%d",&n,&m)!=EOF) { if(n==0&&m==0) return 0; printf("Case %d:\n",++T); init(); work(); } return 0; }