習題:Daleks' Invasion (hard)(LCA&冰茶姬)
阿新 • • 發佈:2020-08-24
題目
思路
我們隨便找一棵最小生成樹
之後將邊分成兩種:樹邊和非樹邊、
如果是非樹邊很好處理,直接LCA求最大值即可
考慮不是樹邊的情況,
如果把這條樹邊切開,有很多邊連線兩個連通塊,我們所需要的知道的是除了這條邊另外的所有邊的最小值
這些最小值可以用樹鏈剖分暴力維護,
當然也可以將邊排序之後用類似於冰茶姬的方法進行維護
程式碼
#include<iostream> #include<cstring> #include<algorithm> #include<vector> using namespace std; namespace ufs { int fa[100005]; void makeset(int n) { for(int i=1;i<=n;i++) fa[i]=i; } int findset(int x) { if(fa[x]==x) return x; return fa[x]=findset(fa[x]); } void merge(int u,int v) { int a=findset(u); int b=findset(v); fa[a]=b; } } using namespace ufs; struct edge { int u,v; long long w; int id; friend bool operator < (const edge &a,const edge &b) { return a.w<b.w; } }a[1000005]; struct node { int e; long long w; }; int n,m; int fath[100005],dep[100005],dp_ind[100005][25]; long long dp_w[100005][25]; long long ans[1000005],w[100005],val[100005]; bool vis[1000005]; vector<node> g[100005]; void dfs(int u,int fa) { dep[u]=dep[fa]+1; for(int i=1;i<=20;i++) { dp_ind[u][i]=dp_ind[dp_ind[u][i-1]][i-1]; dp_w[u][i]=max(dp_w[u][i-1],dp_w[dp_ind[u][i-1]][i-1]); } for(int i=0;i<g[u].size();i++) { int v=g[u][i].e; if(v!=fa) { fath[v]=u; dp_ind[v][0]=u; dp_w[v][0]=g[u][i].w; w[v]=g[u][i].w; dfs(v,u); } } } long long lca(int u,int v) { long long maxx=0; if(u==v) return 0; if(dep[u]>dep[v]) swap(u,v); for(int i=20;i>=0;i--) if(dep[u]<=dep[dp_ind[v][i]]) { maxx=max(maxx,dp_w[v][i]); v=dp_ind[v][i]; } if(u==v) return maxx; for(int i=20;i>=0;i--) if(dp_ind[u][i]!=dp_ind[v][i]) { maxx=max(maxx,max(dp_w[u][i],dp_w[v][i])); u=dp_ind[u][i]; v=dp_ind[v][i]; } return max(maxx,max(dp_w[u][0],dp_w[v][0])); } void col(int u,int v,long long s) { while(u!=v) { if(dep[u]>dep[v]) swap(u,v); val[v]=s; merge(v,fath[v]); v=findset(v); } } int main() { memset(ans,-1,sizeof(ans)); memset(val,-1,sizeof(val)); cin>>n>>m; for(int i=1;i<=m;i++) { cin>>a[i].u>>a[i].v>>a[i].w; a[i].id=i; } sort(a+1,a+m+1); makeset(n); for(int i=1;i<=m;i++) { if(findset(a[i].u)!=findset(a[i].v)) { merge(a[i].u,a[i].v); vis[i]=1; g[a[i].u].push_back((node){a[i].v,a[i].w}); g[a[i].v].push_back((node){a[i].u,a[i].w}); } } dfs(1,0); makeset(n); for(int i=1;i<=m;i++) if(dep[a[i].u]>dep[a[i].v]) swap(a[i].u,a[i].v); for(int i=1;i<=m;i++) if(vis[i]==0) col(findset(a[i].u),findset(a[i].v),a[i].w); for(int i=1;i<=m;i++) { if(vis[i]==0) ans[a[i].id]=lca(a[i].u,a[i].v); else ans[a[i].id]=val[a[i].v]; } for(int i=1;i<=m;i++) if(ans[i]==-1) cout<<"1000000000\n"; else cout<<ans[i]<<'\n'; return 0; }