题意:给出一个图,再给出q次询问,每次询问包含一条边,求出含这条边的最小生成树的权值
先求一遍最小生成树,对于每一次询问,假如这一条边在最小生成树上边那就无所谓了,如果不在的话,就求出这条边的两个点之间的边的最大值,将其去掉,换上我们要加的边即可,找出这两点间边的最大值用lca即可实现
#include<iostream>
#include<cstdio>
#include<cstring>
#include<map>
#include<algorithm>
using namespace std;
const int maxm=2e5+7;
const int maxn=1e5+7;
typedef pair<int,int> P;
struct LDJ
{
int u;
int v;
int val;
}node[maxm];
struct Node
{
int to;
int val;
int next;
}edge[maxm<<1];
int n,m;
int cnt;
int head[maxn];
int tree[maxn];
int dep[maxn];
bool vis[maxn];
int par[maxn][110];
int maxx[maxn][110];
map<P,int> ma;
void init()
{
cnt=0;
memset(head,-1,sizeof(head));
memset(par,-1,sizeof(par));
memset(vis,false,sizeof(vis));
memset(dep,-1,sizeof(dep));
memset(maxx,-1,sizeof(maxx));
for(int i=0;i<maxn;i++)
{
tree[i]=i;
}
ma.clear();
return;
}
void add(int u,int v,int val)
{
edge[cnt].to=v;
edge[cnt].val=val;
edge[cnt].next=head[u];
head[u]=cnt++;
return;
}
bool cmp(LDJ a,LDJ b)
{
return a.val<b.val;
}
int find(int x)
{
return tree[x]==x?x:tree[x]=find(tree[x]);
}
void merge(int u,int v)
{
int x=find(u);
int y=find(v);
if(x!=y)
{
tree[x]=y;
}
return;
}
int kruskal()
{
int sum=0;
int res=0;
for(int i=0;i<m;i++)
{
int u=node[i].u;
int v=node[i].v;
if(find(u)!=find(v))
{
merge(u,v);
sum++;
add(node[i].u,node[i].v,node[i].val);
add(node[i].v,node[i].u,node[i].val);
res+=node[i].val;
if(sum==n-1) break;
}
}
return res;
}
void dfs(int node,int fa,int depth)
{
vis[node]=true;
dep[node]=depth;
par[node][0]=fa;
for(int i=head[node];~i;i=edge[i].next)
{
int v=edge[i].to;
if(v==fa||vis[v]) continue;
maxx[v][0]=edge[i].val;
dfs(v,node,depth+1);
}
return;
}
void lca_init()
{
for(int j=1;(1<<j)<=n;j++)
{
for(int i=1;i<=n;i++)
{
par[i][j]=par[par[i][j-1]][j-1];
maxx[i][j]=max(maxx[i][j-1],maxx[par[i][j-1]][j-1]);
}
}
}
int lca(int x,int y)
{
int ans=-1;
if(dep[x]<dep[y])
{
swap(x,y);
}
int sub=dep[x]-dep[y];
for(int i=0;(1<<i)<=sub;i++)
{
if((1<<i)&sub)
{
ans=max(ans,maxx[x][i]);
x=par[x][i];
}
}
if(x==y) return ans;
for(int i=20;i>=0;i--)
{
if(par[x][i]!=par[y][i])
{
ans=max(ans,maxx[x][i]);
ans=max(ans,maxx[y][i]);
x=par[x][i];
y=par[y][i];
}
}
ans=max(ans,maxx[x][0]);
ans=max(ans,maxx[y][0]);
return ans;
}
int main()
{
while(~scanf("%d%d",&n,&m))
{
init();
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&node[i].u,&node[i].v,&node[i].val);
ma[make_pair(node[i].u,node[i].v)]=node[i].val;
}
sort(node,node+m,cmp);
int res=kruskal();
dfs(1,-1,1);
lca_init();
int q;
scanf("%d",&q);
while(q--)
{
int u,v;
scanf("%d%d",&u,&v);
printf("%d\n",res-lca(u,v)+ma[make_pair(u,v)]);
}
}
return 0;
}