zoukankan      html  css  js  c++  java
  • CF Educational Codeforces Round 3 E. Minimum spanning tree for each edge 最小生成树变种

    题目链接:http://codeforces.com/problemset/problem/609/E

    大致就是有一棵树,对于每一条边,询问包含这条边,最小的一个生成树的权值。

    做法就是先求一次最小生成树,标记最小生成树上的边,对于这些边,直接就是原始最小生成树。否则必然可以在去掉u到v路径上最长边,再加上边u->v,这一定是包含此边最小的生成树。

    查询最长边,可以用树链剖分,也可以树上倍增。

      1 #include <iostream>
      2 #include <vector>
      3 #include <algorithm>
      4 #include <string>
      5 #include <string.h>
      6 #include <stdio.h>
      7 #include <math.h>
      8 #include <stdlib.h>
      9 #include <queue>
     10 #include <stack>
     11 #include <map>
     12 #include <set>
     13 #include <ctime>
     14 #include <cassert>
     15 
     16 using namespace std;
     17 
     18 
     19 const int N=2e5+10;
     20 const int INF=0x3f3f3f3f;
     21 struct Node {
     22     int u,v,w;
     23     int id;
     24     bool operator < (const Node &o) const {
     25         return w<o.w;
     26     }
     27 }node[N];
     28 struct Edge{
     29     int to,next,w;
     30 }edge[N<<1];
     31 int idx,head[N];
     32 void addedge(int u,int v,int w){
     33     ++idx;
     34     edge[idx].to=v;
     35     edge[idx].next=head[u];
     36     edge[idx].w=w;
     37     head[u]=idx;
     38 }
     39 int dep[N];
     40 int par[N][23];
     41 int dis[N][23];
     42 void dfs(int u,int f,int d){
     43     dep[u]=d;
     44     for (int k=head[u];k;k=edge[k].next){
     45         int v=edge[k].to;
     46         if (v==f) continue;
     47         par[v][0]=u;
     48         dis[v][0]=edge[k].w;
     49         dfs(v,u,d+1);
     50     }
     51 }
     52 int kthA(int u,int k) {
     53     for (int i=21;i>=0;i--) {
     54         if (k>=(1<<i)) {
     55             k-=(1<<i);
     56             u=par[u][i];
     57         }
     58     }
     59     return u;
     60 }
     61 int kthD(int u,int k) {
     62     int ret=0;
     63     for (int i=21;i>=0;i--) {
     64         if (k>=(1<<i)) {
     65             k-=(1<<i);
     66             ret=max(ret,dis[u][i]);
     67             u=par[u][i];
     68         }
     69     }
     70     return ret;
     71 }
     72 void calc(int n) {
     73     for (int i=1;i<=21;i++) {
     74         int k=1<<(i-1);
     75         for (int j=1;j<=n;j++) {
     76             par[j][i]=par[par[j][i-1]][i-1];
     77             dis[j][i]=max(dis[j][i-1],dis[par[j][i-1]][i-1]);
     78         }
     79     }
     80 }
     81 int get(int u,int v){
     82     if(dep[u]<dep[v])swap(u,v);
     83     int ret=kthD(u,dep[u]-dep[v]);
     84     u=kthA(u,dep[u]-dep[v]);
     85     if(u==v)return ret;
     86     for(int i=21;i>=0;i--){
     87         if(par[u][i]==par[v][i])continue;
     88         ret=max(ret,dis[u][i]);
     89         ret=max(ret,dis[v][i]);
     90         u=par[u][i];
     91         v=par[v][i];
     92     }
     93     ret=max(ret,dis[u][0]);
     94     ret=max(ret,dis[v][0]);
     95     return ret;
     96 }
     97 int fa[N];
     98 int find(int x) {
     99     if (fa[x]==x)
    100         return x;
    101     return fa[x]=find(fa[x]);
    102 }
    103 bool mark[N];
    104 long long ret[N];
    105 int main () {
    106     ios_base::sync_with_stdio(false);
    107     int n,m;
    108     while (cin>>n>>m) {
    109         for (int i=1;i<=m;i++) {
    110             cin>>node[i].u>>node[i].v>>node[i].w;
    111             node[i].id=i;
    112             mark[i]=false;
    113         }
    114         sort(node+1,node+1+m);
    115         long long sum=0;
    116         for (int i=1;i<=n;i++)
    117             fa[i]=i;
    118         idx=1;memset(head,0,sizeof head);
    119         for (int i=1;i<=m;i++) {
    120             int u=node[i].u;
    121             int v=node[i].v;
    122             int w=node[i].w;
    123             int id=node[i].id;
    124             int fu=find(u);
    125             int fv=find(v);
    126             if (fu==fv) continue;
    127             fa[fu]=fv;
    128             sum+=w;
    129             mark[id]=true;
    130             addedge(u,v,w);
    131             addedge(v,u,w);
    132         }
    133         dfs(1,-1,1);
    134         calc(n);
    135         for (int i=1;i<=m;i++) {
    136             int id=node[i].id;
    137             int u=node[i].u;
    138             int v=node[i].v;
    139             int w=node[i].w;
    140             if (mark[id]) ret[id]=sum;
    141             else {
    142                 int mx=get(u,v);
    143                 ret[id]=sum+w-mx;
    144             }
    145         }
    146         for (int i=1;i<=m;i++)
    147             cout<<ret[i]<<endl;
    148     }
    149     return 0;
    150 }
    View Code
  • 相关阅读:
    动态调用web服务
    组件设计实战--组件之间的关系 (Event、依赖倒置、Bridge)
    .NET平台下可复用的Tcp通信层实现
    推荐所有的.NET开发人员阅读《J2EE Development without EJB》
    关于跨程序集的反射(续)
    IoC与DI (转载)
    某公司的一道机考题的解答
    使用 EmptyClass 避免条件判断
    EsbAOP应用--权限管理
    企业(分布式)计算十大谬误
  • 原文地址:https://www.cnblogs.com/micrari/p/5178457.html
Copyright © 2011-2022 走看看