您的位置:首页 > 其它

Minimum spanning tree for each edge CodeForces - 609E (Lca+最小生成树)

2018-03-22 15:42 513 查看
Connected undirected weighted graph without self-loops and multiple edges is given. Graph contains n vertices and m edges.
For each edge (u, v) find the minimal possible weight of the spanning tree that contains the edge (u, v).
The weight of the spanning tree is the sum of weights of all edges included in spanning tree.
InputFirst line contains two integers n and m (1 ≤ n ≤ 2·105, n - 1 ≤ m ≤ 2·105) — the number of vertices and edges in graph.
Each of the next m lines contains three integers ui, vi, wi (1 ≤ ui, vi ≤ n, ui ≠ vi, 1 ≤ wi ≤ 109) — the endpoints of the i-th edge and its weight.
OutputPrint m lines. i-th line should contain the minimal possible weight of the spanning tree that contains i-th edge.
The edges are numbered from 1 to m in order of their appearing in input.
ExampleInput
5 7
1 2 3
1 3 1
1 4 5
2 3 2
2 5 3
3 4 2
4 5 4
Output
9
8
11
8
8
8
9
#include<cstdio>
#include<string>
#include<algorithm>
#include<vector>
#include<cmath>
#define bug(x) printf("%d*****\n",x)
using namespace std;

typedef long long ll;
const int maxn=2e5+10;

struct Edge{
int u,v;
ll w;
int id,flag;
Edge(){}
Edge(int _u,int _v,ll _w,int _id):u(_u),v(_v),w(_w),id(_id){}
}edge[maxn];

struct Node{
int v;
ll w;
Node(){}
Node(int _v,ll _w):v(_v),w(_w){}
}now;
vector<Node> vec[maxn];

int dep[maxn],rt[maxn][20],pre[maxn];
ll dis[maxn],Max[maxn][20];
int n,m;

int find_rt(int x){
return pre[x]==x?x:pre[x]=find_rt(pre[x]);
}

ll get_tree(){
ll ans=0;
int cnt=0;
for(int i=1;i<=n;i++) pre[i]=i;
for(int i=1;i<=m;i++){
int u=edge[i].u,v=edge[i].v;
ll w=edge[i].w;
int ru=find_rt(u),rv=find_rt(v);
if(ru!=rv){
ans+=edge[i].w;
edge[i].flag=1;
pre[ru]=rv;
cnt++;
now=Node(v,w);
vec[u].push_back(now);
now=Node(u,w);
vec[v].push_back(now);
//printf("u:%d v:%d w:%lld\n",u,v,w);
if(cnt+1==n) break;
}
}
return ans;
}
int cmp1(Edge a,Edge b){
return a.w<b.w;
}
int cmp2(Edge a,Edge b){
return a.id<b.id;
}

int vis[maxn];
void dfs(int u){
vis[u]=1;
//printf("u:%d\n",u);
for(int i=0;i<vec[u].size();i++){
int v=vec[u][i].v;
ll w=vec[u][i].w;
if(!vis[v]) {
rt[v][0]=u;
dis[v]=dis[u]+w;
dep[v]=dep[u]+1;
Max[v][0]=w;
dfs(v);
}
}
}

void get_rt(){
for(int i=1;(1<<i)<=n;i++){
for(int j=1;j<=n;j++){
rt[j][i]=rt[rt[j][i-1]][i-1];
Max[j][i]=max(Max[j][i-1],Max[rt[j][i-1]][i-1]);
// printf("i:%d j:%d maxw:%lld\n",i,j,Max[j][i]);
}
}
}

int get_lca(int u,int v,ll& ans){
if(dep[u]>dep[v]) swap(u,v);
int dif=dep[v]-dep[u];
ll tmp1=0,tmp2=0;
for(int i=0;(1<<i)<=dif;i++){
if(dif&(1<<i)){
tmp2=max(tmp2,Max[v][i]);
v=rt[v][i];
// printf("v:%d tmp2:%lld i:%d\n",v,tmp2,i);
}
}
// printf("u:%d v:%d tmp2:%lld ",u,v,tmp2);
if(u!=v){
for(int i=(int)log2(n);i>=0;i--){
if(rt[u][i]!=rt[v][i]){
tmp1=max(tmp1,Max[u][i]);
tmp2=max(tmp2,Max[v][i]);
u=rt[u][i],v=rt[v][i];
}
}
tmp1=max(tmp1,Max[u][0]);
tmp2=max(tmp2,Max[v][0]);
u=rt[u][0];
}
ans=max(tmp1,tmp2);
// printf(" %lld\n",ans);
return u;
}

int main(){
scanf("%d %d",&n,&m);
for(int i=1;i<=m;i++){
int u,v;ll w;
scanf("%d %d %lld",&u,&v,&w);
edge[i]=Edge(u,v,w,i);
edge[i].flag=0;
/* 在这里赋值,对于边来说没哟什么用,只能是做错
now=Node(v,w);
vec[u].push_back(now);
now=Node(u,w);
vec[v].push_back(now);
*/
}
ll sum=0;
sort(edge+1,edge+m+1,cmp1);
sum=get_tree();
sort(edge+1,edge+m+1,cmp2);
dis[1]=dep[1]=0;

dfs(1);
// printf("sum:%lld\n",sum);
get_rt();
for(int i=1;i<=m;i++){
int u=edge[i].u,v=edge[i].v;
if(edge[i].flag){
printf("%lld\n",sum);
continue;
}
ll ans;
int r=get_lca(u,v,ans);
// printf("u:%d v:%d r:%d ans:%lld\n",u,v,r,ans);
printf("%lld\n",sum+edge[i].w-ans);
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐