Imperial roads
2017-2018 ACM-ICPC Latin American Regional Programming Contest, problem: (I) Imperial roads
题目链接:Codeforces GYM 101889,Problem I。
题目大意
给定
数据范围:
思路
显然,这是一个生成树问题。
类似于次小生成树,跑一个替换边操作,非常板子,没什么好说的。
kruskal 最小生成树时间复杂度:
求 LCA 并替换边时间复杂度:
总时间复杂度:
附:次小生成树。
代码
#include <bits/stdc++.h>
#define ll long long
using namespace std;
const int N = 1e5 + 5;
struct edge {
int to,nx,wt;
} eg[N*4];
int hd[N],tot;
void adeg(int u,int v,int w) {
eg[++tot]={v,hd[u],w};
hd[u]=tot;
}
int fa[N];
int find(int u) {
if(fa[u]==u) return u;
return fa[u]=find(fa[u]);
}
void merge(int u,int v) {
u=find(u),v=find(v);
fa[u]=v;
}
vector<pair<pair<int,int>,int> > g;
bool cmp(pair<pair<int,int>,int> a,pair<pair<int,int>,int> b){
return a.second<b.second;
}
set<pair<int,int> > st;
map<pair<int,int>,int> mp;
ll kruskal(int n,int m) {
ll res=0;
sort(g.begin(),g.end(),cmp);
for(int i=1;i<=n;++i) fa[i]=i;
for(int i=0;i<m;++i) {
int u=g[i].first.first,v=g[i].first.second;
int w=g[i].second;
if(find(u)==find(v)) continue;
adeg(u,v,w);
adeg(v,u,w);
st.insert(make_pair(u,v));
st.insert(make_pair(v,u));
res+=w;
merge(u,v);
} return res;
}
int f[N][20],dep[N],dis[N][20];
void dfs(int u,int fa) {
f[u][0]=fa;
dep[u]=dep[fa]+1;
for(int i=1;i<20;++i)
f[u][i]=f[f[u][i-1]][i-1],
dis[u][i]=max(dis[u][i-1],dis[f[u][i-1]][i-1]);
for(int i=hd[u];i;i=eg[i].nx) {
int to=eg[i].to;
if(to==fa) continue;
dis[to][0]=eg[i].wt;
dfs(to,u);
}
}
int lca(int u,int v) {
if(dep[u]<dep[v]) swap(u,v); //dep[u]>=dep[v]
for(int i=19;i>=0;--i)
if(dep[f[u][i]]>=dep[v])
u=f[u][i];
if(u==v) return u;
for(int i=19;i>=0;--i)
if(f[u][i]!=f[v][i])
u=f[u][i],v=f[v][i];
if(u==v) return u;
return f[u][0];
}
int maxpath(int u,int fa) {
int mx=0;
for(int i=19;i>=0;--i)
if(dep[f[u][i]]>=dep[fa])
mx=max(dis[u][i],mx),
u=f[u][i];
return mx;
}
signed main() {
ios::sync_with_stdio(false);
cin.tie(nullptr),
cout.tie(nullptr);
int n,m;
cin>>n>>m;
for(int i=1;i<=m;++i) {
int u,v,w;
cin>>u>>v>>w;
g.push_back({{u,v},w});
mp.insert({{u,v},w});
mp.insert({{v,u},w});
}
ll res=kruskal(n,m);
dfs(1,0);
int q;
cin>>q;
while(q--) {
int u,v;
cin>>u>>v;
if(st.find(make_pair(u,v))!=st.end())
cout<<res<<'\n';
else {
ll w=mp[make_pair(u,v)];
int LCA=lca(u,v);
ll zc=max(maxpath(u,LCA),maxpath(v,LCA));
cout<<res-zc+w<<'\n';
}
}
return 0;
}