标签: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