码迷,mamicode.com
首页 > 其他好文 > 详细

cf 609E.Minimum spanning tree for each edge

时间:2017-02-05 19:37:42      阅读:172      评论:0      收藏:0      [点我收藏+]

标签:nim   name   minimum   find   fat   情况   sum   生成   i++   

最小生成树,lca(树链剖分(太难搞,不会写))

问存在这条边的最小生成树,2种情况。1.这条边在原始最小生成树上。2.加上这条半形成一个环(加上),那么就找原来这条边2端点间的最大边就好(减去)。(sum+val-max)

(代码冗长)

  1 #include<bits/stdc++.h>
  2 #define LL long long 
  3 #define  N 100005
  4 using namespace std;
  5 inline int ra()
  6 {
  7     int x=0,f=1; char ch=getchar();
  8     while (ch<0 || ch>9) {if (ch==-) f=-1; ch=getchar();}
  9     while (ch>=0 && ch<=9) {x=x*10+ch-0; ch=getchar();}
 10     return x*f;
 11 }
 12 struct node{
 13     int x,y,id,v;
 14 }a[N<<1];
 15 struct data{
 16     int to,next,v;
 17 }e[N<<2];
 18 int n,m,deep[N<<1],fa[N<<1][21];
 19 int father[N<<1],cnt;
 20 LL sum;
 21 int mx[N<<1][21],head[N<<1];
 22 bool vis[N<<1];
 23 void insert(int x, int y, int v)
 24 {
 25     e[++cnt].next=head[x];
 26     e[cnt].to=y;
 27     e[cnt].v=v;
 28     head[x]=cnt;
 29 }
 30 int find(int x)
 31 {
 32     return father[x]==x?x:father[x]=find(father[x]);
 33 }
 34 bool cmp(node a, node b)
 35 {
 36     return a.v<b.v;
 37 }
 38 bool cmpid(node a, node b)
 39 {
 40     return a.id<b.id;
 41 }
 42 void dfs(int x, int f)
 43 {
 44     for (int i=1; i<=20; i++)
 45     {
 46         fa[x][i]=fa[fa[x][i-1]][i-1];
 47         mx[x][i]=max(mx[x][i-1],mx[fa[x][i-1]][i-1]);
 48     }
 49     for (int i=head[x];i;i=e[i].next)
 50     {
 51         if (e[i].to==f) continue;
 52         fa[e[i].to][0]=x;
 53         mx[e[i].to][0]=e[i].v;
 54         deep[e[i].to]=deep[x]+1;
 55         dfs(e[i].to,x);
 56     }
 57 }
 58 int getans(int x, int y)
 59 {
 60     int ans=0;
 61     if (deep[x]<deep[y]) swap(x,y);
 62     int t=deep[x]-deep[y];
 63     for (int i=0; i<=20; i++)
 64         if (t&(1<<i)) ans=max(ans,mx[x][i]),x=fa[x][i];
 65     for (int i=20; i>=0; i--)
 66         if (fa[x][i]!=fa[y][i])
 67         {
 68             ans=max(ans,max(mx[x][i],mx[y][i]));
 69             x=fa[x][i]; y=fa[y][i];
 70         }
 71     if (x!=y) return max(ans,max(mx[x][0],mx[y][0]));
 72     return ans;
 73 }
 74 int main()
 75 {
 76     n=ra(); m=ra();
 77     for (int i=1; i<=m; i++)
 78     {
 79         int x=ra(),y=ra(),v=ra();
 80         a[i].x=x; a[i].y=y; a[i].v=v; a[i].id=i;
 81     }
 82     sort(a+1,a+m+1,cmp); int tot=0;
 83     for (int i=1; i<=n; i++) father[i]=i;
 84     for (int i=1; i<=m; i++)
 85     {
 86         int q=find(a[i].x),p=find(a[i].y);
 87         if (p!=q)
 88         {
 89             vis[a[i].id]=1;
 90             father[p]=q;
 91             sum+=a[i].v;
 92             tot++;
 93             insert(a[i].x,a[i].y,a[i].v);
 94             insert(a[i].y,a[i].x,a[i].v);
 95     //        cout<<a[i].x<<"   "<<a[i].y<<"    "<<a[i].v<<endl;
 96         }
 97         if (tot==n-1) break;
 98     }
 99     dfs(1,0);
100     sort(a+1,a+m+1,cmpid);
101     for (int i=1; i<=m; i++)
102     {
103         if (vis[i]) printf("%I64d\n",sum);
104         else {
105             cout<<sum+(LL)a[i].v-(LL)getans(a[i].x,a[i].y)<<endl;
106         //    cout<<getans(a[i].x,a[i].y);while (1);
107         }
108     }
109     return 0;
110 }

 

cf 609E.Minimum spanning tree for each edge

标签:nim   name   minimum   find   fat   情况   sum   生成   i++   

原文地址:http://www.cnblogs.com/ccd2333/p/6368254.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!