2020-1024=996
Fine product
10.24祝各位coder编码有成,学业进步,工作顺利,升职加薪!!!
Pre-knowledge
1. Prim algorithm and Kurskal algorithm to find the minimum spanning tree
2. LCA to find the nearest common ancestor between two points on the tree
concept
If the minimum spanning tree edge set is selected EM, a small set of edges Strictly spanning tree is selected ES, you need to meet:
The idea
requires the second-smallest spanning tree, that is, the operation of adding and deleting edges on the minimum spanning tree to obtain the second-smallest spanning tree
If we find the second-smallest spanning tree, and we arbitrarily take an edge between two points u and v on the tree, then a ring must be generated at this time . We need to delete an edge from this ring to maintain the structure of the tree. Then the weight of the edge I deleted and the added edge should be as equal as possible (but not equal), because in this way, the weight of the new tree may increase less.
Step
1. Find the minimum spanning tree
2. Find the maximum and second largest value between any two points on the minimum spanning tree
3. Enumerate the extra edges, add them to the minimum spanning tree, and delete one from the generated ring Edge
4. Take the smallest of the weights of the new trees generated multiple times
Specific operation When
seeking the maximum value and the second maximum value between any two points, you can use the idea of lca, the method of multiplication on the tree.
If the added edge connects the two points u and v, then we can find the maximum or the second largest value from u to lca respectively. The same is true for v, and then the two are the largest.
Because the weight of a[i].w of the added edge must be greater than or equal to the weight of the largest edge on the tree, if the maximum value of the bright spot on the tree is equal to a[i].w, we take the second smallest value , Only in this way can the weight of the new tree increase as small as possible
note
The second largest value between any two points on the tree should be initialized to negative infinity! ! !
If not, because if the edge weights in the minimum spanning tree are all equal, and then the weight of an edge and the weight on the tree are also equal, the answer is min-0+w;
then there is another edge The weight of is (w+10) and the answer is min-(w)+(w+10);
Because the former is not an answer, but it will be judged as an answer, because he is small (under certain circumstances where w is satisfied)
(Draw a tree by yourself to understand, it's relatively simple)
Code
#include<iostream>
#include<algorithm>
#include<math.h>
#include<queue>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <stack>
#include <map>
#include <set>
#include <vector>
#include <iomanip>
using namespace std;
typedef long long ll;
typedef pair<int, int> PII;
typedef unsigned long long ull;
const int inf = 0x3f3f3f3f;
const int maxn = 8e5 + 7;
const ll mod = 1000000007;
#define mst(x, a) memset( x,a,sizeof(x) )
#define rep(i, a, b) for(int i=(a);i<=(b);++i)
#define dep(i, a, b) for(int i=(a);i>=(b);--i)
ll read() {
ll x = 0;
char ch = getchar();
while(ch < '0' || ch > '9')ch = getchar();
while(ch >= '0' && ch <= '9')x = (x << 1) + (x << 3) + (ch ^ 48), ch = getchar();
return x;
}
void out(ll x) {
int stackk[40];
if (x < 0) {
putchar('-');
x = -x;
}
if (!x) {
putchar('0');
return;
}
int top = 0;
while (x) stackk[++top] = x % 10, x /= 10;
while (top) putchar(stackk[top--] + '0');
}
ll n,m,p[maxn],cnt,head[maxn],fa[maxn][22],max1[maxn][22];
ll max2[maxn][22],dep[maxn],len,vis[maxn],paid;
struct node {
ll u,v,w;
} a[maxn];
bool cmp(node x,node y) {
return x.w<y.w;
}
struct nodee {
ll u,v,w,next;
} e[maxn];
void add(ll u,ll v,ll w) {
e[cnt].u=u,e[cnt].v=v;
e[cnt].w=w,e[cnt].next=head[u];
head[u]=cnt++;
}
void dfs(ll u,ll p) {
dep[u]=dep[p]+1,fa[u][0]=p;
for(int i=1 ; i<=len ; i++) fa[u][i]=fa[fa[u][i-1]][i-1];
for(int i=head[u]; ~i; i=e[i].next) {
int v=e[i].v;
if(v==p) continue;
max1[v][0]=e[i].w;
dfs(v,u);
}
}
void cal() {
for(int i=1 ; i<=len; i++) {
for(int j=1 ; j<=n; j++) {
max1[j][i]=max(max1[j][i-1],max1[fa[j][i-1]][i-1]);
max2[j][i]=max(max2[j][i-1],max2[fa[j][i-1]][i-1]);
if(max1[j][i-1]<max1[fa[j][i-1]][i-1]) max2[j][i]=max1[j][i-1];
else if(max1[j][i-1]>max1[fa[j][i-1]][i-1]) max2[j][i]=max1[fa[j][i-1]][i-1];
}
}
}
ll lca(ll x,ll y) {
if(dep[x]<dep[y]) swap(x,y);
for(int i=len ; i>=0 ; i--) if(dep[fa[x][i]]>=dep[y]) x=fa[x][i];
if(x==y) return x;
for(int i=len ; i>=0 ; i--)
if(fa[x][i]!=fa[y][i]) x=fa[x][i],y=fa[y][i];
return fa[x][0];
}
ll q(ll x,ll y,ll w) {
ll ans=0;
for(int i=len ; i>=0 ; i--)
if(dep[fa[x][i]]>=dep[y]) {
if(max1[x][i]!=w) ans=max(ans,max1[x][i]);
else ans=max(ans,max2[x][i]);
x=fa[x][i];
}
return ans;
}
ll find(ll x) {
if(p[x]==x) return x;
return p[x]=find(p[x]);
}
int main() {
mst(head,-1);
n=read(),m=read();
len=log2(n)+2;
for(int i=0 ; i<=n ; i++) p[i]=i;
for(int i=1 ; i<=m ; i++) {
a[i].u=read();
a[i].v=read();
a[i].w=read();
}
sort(a+1,a+1+m,cmp);
for(int i=1 ; i<=m ; i++) {
ll u=a[i].u;
ll v=a[i].v;
if(find(u)==find(v)) continue;
p[find(u)]=find(v);
add(u,v,a[i].w);
add(v,u,a[i].w);
vis[i]=1,paid+=a[i].w;
}
max2[1][0]=-1e17;
dfs(1,-1);
cal();
ll ans=1e17;
for(int i=1 ; i<=m ; i++) {
if(vis[i]) continue;
ll u=a[i].u;
ll v=a[i].v;
ll lc=lca(u,v);
ll temp1=q(u,lc,a[i].w);
ll temp2=q(v,lc,a[i].w);
ans=min(ans,paid-max(temp1,temp2)+a[i].w);
}
printf("%lld",ans);
return 0;
}
/*
*/