Statement
題目大意
給定一棵基環外向樹,和若干組詢問,對于每次獨立的詢問都指定一些起點和一些終點,你刪去一些邊,使得從任意起點出發都無法到達終點,并讓刪去的邊的編號的最小值最大,求這個最大的最小值。
?
題解
不難發現,在基環外向樹中,任意兩個點之間至多有唯一條簡單路徑,且對于這道題來講非簡單路徑是沒有意義的,因為非簡單路徑一定會囊括一個簡單路徑。這意味著對于每一個終點,至多有一個與之對應的距離最短的起點,使得當你將這條路徑上某一條邊刪掉時,這個起點就不可能被到達了。那么我們顯然會貪心的刪去路徑上編號最大的那一條。由于每一個點的入邊(如果有的話)是唯一的,且沒有修改操作,我們就可以用倍增來求路徑最大值。
現在問題就轉化為如何找每個重點對應的起點,我們分開考慮。
先考慮起點僅通過樹邊到達終點的情況。這個比較好辦,將所有起點按照深度從小到大依次處理,每次把當前起點的深度當做標記覆蓋到以這一起點所代表的的子樹中,這個用線段樹處理即可。做完這件事以后,掃一遍終點,如果它已經被覆蓋到了,那么就通過標記和深度直接算出起點和終點的距離,倍增求一下最大值,最終答案取$\min$,然后把這個終點刪掉即可。
剩下的終點一定滿足沒有一個起點能夠僅通過樹邊到達,所以必須通過一部分環上的邊,因而不在環上的起點也沒用了,刪掉即可。我們直接讓剩下的終點先跳到它們所在的樹的樹根上,并在路徑上的邊求編號的$\max$,如果樹根不在環上或樹根所在的環上沒有任何起點,那么這個中點本身就不可被任何起點到達,對答案沒有貢獻。然后對于每一個環,將起點和終點都按照順時針排序,枚舉每一個終點都一定能找到它的前驅起點,更新答案即可。
復雜度$O(N+\sum\limits_{i=1}^{m} (t_i+f_i)\log N)$
?
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> #define LL long long #define M 200020 #define mid ((l+r)>>1) using namespace std; const int BufferSize=1<<19; char buffer[BufferSize],*head,*tail; inline char Getchar() {if(head==tail) {int l=fread(buffer,1,BufferSize,stdin);tail=(head=buffer)+l;} return *head++; } int read(){int nm=0,fh=1; char cw=Getchar();for(;!isdigit(cw);cw=Getchar()) if(cw=='-') fh=-fh;for(;isdigit(cw);cw=Getchar()) nm=nm*10+(cw-'0');return nm*fh; } int n,m,fs[M],fa[M][19],t[M][19],tmp=1,dfn[M],sz[M],od[M],to[M],nt[M]; int cnt,id[M],dep[M],tg[M<<2],maxn,tp[M],CT[M]; int S1[M],S2[M],C1[M],C2[M]; bool cir[M],vis[M],ist[M]; void link(int x,int y){nt[tmp]=fs[x],fs[x]=tmp,to[tmp++]=y;} void dfs(int x){sz[x]=1,dfn[x]=++cnt,vis[x]=true;for(int i=fs[x];i!=-1;i=nt[i]){if(cir[to[i]]) continue; id[to[i]]=id[x];dep[to[i]]=dep[x]+1,tp[to[i]]=tp[x];dfs(to[i]),sz[x]+=sz[to[i]];} } bool cmpd(int x,int y){return dep[x]<dep[y];} bool cmpc(int x,int y){if(id[tp[x]]!=id[tp[y]]) return id[tp[x]]<id[tp[y]];return od[tp[x]]>od[tp[y]];} void pushdown(int x){if(tg[x]!=-1) tg[x<<1]=tg[x<<1|1]=tg[x],tg[x]=-1;} void upd(int x,int l,int r,int L,int R,int D){if(r<L||R<l) return;if(L<=l&&r<=R){tg[x]=D;return;}pushdown(x),upd(x<<1,l,mid,L,R,D),upd(x<<1|1,mid+1,r,L,R,D); } int qry(int x,int l,int r,int pos){if(l==r) return tg[x]; pushdown(x);if(pos<=mid) return qry(x<<1,l,mid,pos); return qry(x<<1|1,mid+1,r,pos); } int dp(int x,int dt){int res=0;for(int k=0;dt>0;k++,dt>>=1) if(dt&1) res=max(res,t[x][k]),x=fa[x][k];return !res?m+1:res; } int main(){n=read(),m=read(),memset(fs,-1,sizeof(fs));for(int i=1;i<=m;i++){int u=read(),v=read();fa[v][0]=u,t[v][0]=i,link(u,v);}for(int i=1;i<=n;i++){if(vis[i]) continue; int now;for(vis[now=i]=true;fa[now][0]&&!vis[fa[now][0]];now=fa[now][0]) vis[fa[now][0]]=true;if(!fa[now][0]){ist[now]=true,t[now][0]=0;id[now]=++maxn,tp[now]=now,dfs(now); continue;} for(maxn++;!cir[now];now=fa[now][0]){cir[now]=true,id[now]=maxn,tp[now]=now;od[fa[now][0]]=od[now]+1,CT[maxn]++;} dfs(now);for(now=fa[now][0];od[now]!=CT[maxn];now=fa[now][0]) dfs(now);}for(int k=1;k<19;k++){for(int i=1;i<=n;i++){fa[i][k]=fa[fa[i][k-1]][k-1];t[i][k]=max(t[i][k-1],t[fa[i][k-1]][k-1]);}}for(int Qs=read();Qs;--Qs){upd(1,1,n,1,n,-2);int now,m1=read(),m2,st=1,ed=1,ans=m+1,n1=0,n2=0,ps=1;for(int i=1;i<=m1;i++) S1[i]=read(); m2=read();for(int i=1;i<=m2;i++) S2[i]=read(); sort(S1+1,S1+m1+1,cmpd);for(int i=1;i<=m1;i++) upd(1,1,n,dfn[S1[i]],dfn[S1[i]]+sz[S1[i]]-1,dep[S1[i]]);for(int i=1;i<=m2;i++){if(!dep[S2[i]]){if(cir[tp[S2[i]]]) C2[++n2]=S2[i];continue;}int num=qry(1,1,n,dfn[S2[i]]),cst;if(num>=0) cst=dp(S2[i],dep[S2[i]]-num),ans=min(ans,cst);else C2[++n2]=S2[i];}for(int i=1;i<=m1;i++) if(cir[S1[i]]) C1[++n1]=S1[i];sort(C1+1,C1+n1+1,cmpc),sort(C2+1,C2+n2+1,cmpc),C1[n1+1]=C2[n2+1]=0;for(int i=1;i<=n2;i++){while(ed<n1&&id[C1[st]]<id[tp[C2[i]]]) st=ed+1,ed=ps=st;if(id[C1[st]]<id[tp[C2[i]]]) break;if(id[C1[st]]>id[tp[C2[i]]]) continue;while(ed<n1&&id[C1[st]]==id[C1[ed+1]]) ed++;now=cir[C2[i]]?0:dp(C2[i],dep[C2[i]]),C2[i]=tp[C2[i]];while(ps<ed&&od[C1[ps+1]]>od[C2[i]]) ps++;if(od[C1[ps]]>od[C2[i]]) now=max(now,dp(C2[i],od[C1[ps]]-od[C2[i]]));else now=max(now,dp(C2[i],CT[id[C1[ps]]]+od[C1[ed]]-od[C2[i]]));if(now) ans=min(ans,now);}if(ans==m+1) puts("OK"); else printf("%d\n",ans);}return 0; }?
?
轉載于:https://www.cnblogs.com/OYJason/p/9728405.html
總結
- 上一篇: 阿里云 Ubuntu16.04 部署 L
- 下一篇: ocrosoft Contest1316