Title Link: http://acm.hdu.edu.cn/showproblem.php?pid=4126
Test instructions: Give a picture of 3,000 points, there are 10,000 operations: to obtain the weight of a certain edge of the smallest spanning tree, and finally output 10,000 operations to obtain the average value of the minimum spanning tree weights.
Analysis:
For each query, the edge between A and b is increased to c, and there are two situations:
1. The value of the smallest spanning tree at this time will not change if the edge is not originally in the minimum spanning tree.
2. If the edge is in the original minimum spanning tree, then this time the added edge is removed from the original minimum spanning tree, when the spanning tree is divided into two separate parts, it can be proved that the minimum spanning tree must be the smallest of the two parts connected to the side.
Set DP[I][J] To remove the smallest edge of the smallest spanning tree (i,j) into two unicom parts, once again connecting them again to the minimum side length.
So for each point Pos starts down DFS, constantly maintaining a dis[pos][u] (U is another point on the tree) the minimum value of ans, after searching the sub-nodes of the subtree to let the minimum value ans=dp[u][v], because the broken edge (U, V) after the POS connects a node on the V subtree so that two subtrees with the root node of U and V are connected again.
#pragmaComment (linker, "/stack:102400000,102400000")#include<cstdio>#include<cstring>#include<cmath>#include<iostream>#include<algorithm>#include<queue>#include<cstdlib>#include<stack>#include<vector>#include<Set>#include<map>#defineLL Long Long#defineMoD 1000000007#defineINF 0x3f3f3f3f#defineN 3010#defineFILL (A, B) (Memset (A,b,sizeof (a)))using namespacestd;structedge{intu,v,w; BOOL operator< (ConstEdge &a)Const { returnw<A.W; }}e[n*N];intDis[n][n],dp[n][n],vis[n][n],fa[n];intN,m,q;vector<int>G[n];intFindintx) { returnx==fa[x]?x:fa[x]=find (Fa[x]);}voidinit () { for(intI=0; i<n;i++) {Fa[i]=i;g[i].clear (); for(intj=0; j<n;j++) Dis[i][j]=dp[i][j]=inf; } FILL (Vis,0);}intKruskal () {intres=0; for(intI=0; i<m;i++) { intA=find (E[I].U); intb=find (E[I].V); if(a!=b) {Fa[a]=b; Res+=E[I].W; VIS[E[I].U][E[I].V]=vis[e[i].v][e[i].u]=1;//UV This edge is on the smallest spanning treeG[e[i].u].push_back (E[I].V);//constructing the minimum spanning treeG[e[i].v].push_back (E[I].U); } } returnRes;}intDfsintPosintUintFA) { intans=inf; for(intI=0, Size=g[u].size (); i<size;i++) { intv=G[u][i]; if(V==FA)Continue; intmn=DFS (POS,V,U); Ans=min (ans,mn); DP[U][V]=dp[v][u]=min (dp[u][v],mn); } //maintain a minimum distance from a POS to a sub-node on V to ensure that the edge (U,V) is the optimal alternative to the edge, provided that the edge is not known (U,V) on the smallest spanning tree if(Fa!=pos) ans=min (ans,dis[pos][u]); returnans;}intMain () {intA,b,c; while(SCANF ("%d%d", &n,&m) >0) { if(m+n==0) Break; Init (); for(intI=0; i<m;i++) {scanf ("%d%d%d",&e[i].u,&e[i].v,&E[I].W); DIS[E[I].U][E[I].V]=DIS[E[I].V][E[I].U]=E[I].W;//distance of point U point v} sort (E,e+m); intmst=Kruskal (); for(intI=0; i<n;i++) {DFS (i,i,-1); } scanf ("%d",&q); Doublesum=0; for(intI=0; i<q;i++) {scanf ("%d%d%d",&a,&b,&c); if(!Vis[a][b]) {Sum+=MST; } Else{sum+=mst-dis[a][b]+min (c,dp[a][b]); }} printf ("%.4lf\n", sum/q); }}View Code
hdu4126 (minimum spanning tree +dfs)