UVALive 8196 && Gym 101889I Imperial roads(最小生成樹+LCA)
阿新 • • 發佈:2018-12-13
題意:給出一個圖,再給出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; }