这道题和HDU4756是完全一样的。
http://blog.csdn.net/just_water/article/details/11950623
题意:给你一个无向图,有N个点M条边,然后Q个询问,每次询问x , y , z ,意思是边x -> y 的边长增加成z (一定是增加) 。
然后问增加之后的最小生成树。
最后输出Q次询问后最小生成树的平均值。
思路:和上一题完全一样,我们求一次MST之后,求出每两个点之间最近的非树边最短边,然后对于每个询问,首先判断是否是树边,如果不是树边,那么最小生成树的值不变。
如果是树边,那么这条边就有2种取法,取增加后的边,或者x - >y 的非树边最小边,取最小值即可。
#include <set> #include <map> #include <stack> #include <cmath> #include <queue> #include <cstdio> #include <string> #include <vector> #include <iomanip> #include <cstring> #include <iostream> #include <algorithm> #define Max 2505 #define FI first #define SE second #define ll long long #define PI acos(-1.0) #define inf 0x3fffffffffffffffll #define LL(x) ( x << 1 ) #define bug puts("here") #define PII pair<int,int> #define RR(x) ( x << 1 | 1 ) #define mp(a,b) make_pair(a,b) #define mem(a,b) memset(a,b,sizeof(a)) #define REP(i,s,t) for( int i = ( s ) ; i <= ( t ) ; ++ i ) using namespace std; inline void RD(int &ret) { char c; int flag = 1 ; do { c = getchar(); if(c == '-')flag = -1 ; } while(c < '0' || c > '9') ; ret = c - '0'; while((c=getchar()) >= '0' && c <= '9') ret = ret * 10 + ( c - '0' ); ret *= flag ; } #define N 3333 #define M 20000000 int n , m ; ll Map[N][N] ; ll MINE[N][N] ; struct MST{ int s , e ; ll l ; bool operator < (const MST & fk) const{ return l > fk.l ; } } ; void init(){ for (int i = 0 ; i < n ; i ++ )for (int j = 0 ; j < n ; j ++ )MINE[i][j] = Map[i][j] = (i == j) ? 0 : inf ; } ll dis[N] ; bool vis[N] ; priority_queue<MST>qe ; ll mst ; bool ismst[N][N] ; vector<int>G[N] ; void Prim(){ mst = 0 ; mem(ismst , 0) ; while(!qe.empty())qe.pop() ; for (int i = 0 ; i < n ; i ++ )dis[i] = Map[0][i] , vis[i] = 0 , qe.push((MST){0 , i , dis[i]}) ,G[i].clear() ; vis[0] = 1 ; while(!qe.empty()){ MST tp = qe.top() ; qe.pop() ; if(vis[tp.e])continue ; vis[tp.e] = 1 ; mst += dis[tp.e] ; ismst[tp.s][tp.e] = ismst[tp.e][tp.s] = 1 ; G[tp.s].push_back(tp.e) ; G[tp.e].push_back(tp.s) ; MINE[tp.e][tp.s] = MINE[tp.s][tp.e] = inf ; for (int i = 0 ; i < n ; i ++ )if(!vis[i] && dis[i] > Map[tp.e][i])dis[i] = Map[tp.e][i] , qe.push((MST){tp.e , i , dis[i]}) ; } } void dfs(int root , int fa , int now){ int sz = G[now].size() ; for (int i = 0 ; i < sz ; i ++ ){ int e = G[now][i] ; if(fa != e)dfs(root , now , e) , MINE[root][now] = min(MINE[root][now] ,MINE[root][e]) ; } } int st[N * 100] ; int top ; ll NMIN[N][N] ; void dfs(int fa, int now){ int fk = top ; st[ ++ top] = now ;int sz = G[now].size() ; for (int i = 0 ; i < sz ; i ++ ){ int e = G[now][i] ; if(e != fa)dfs(now , e) ; } if(fa != -1){ NMIN[now][fa] = NMIN[fa][now] = inf ; for (int i = fk + 1 ; i <= top ; i ++ )NMIN[now][fa] = NMIN[fa][now] = min(NMIN[fa][now] , MINE[st[i]][fa]) ; } } void solve(){ init() ; while(m --){ int a , b , c ;RD(a) ; RD(b) ; RD(c) ; MINE[a][b] = MINE[b][a] = Map[a][b] = Map[b][a] = c ; } Prim() ; for (int i = 0 ; i < n ; i ++ )dfs(i , -1 , i) ; top = 0 ; dfs(-1 ,0) ; int Q ;cin >> Q ;int fk = Q ; ll ans = 0 ; while(Q -- ){ int x , y , z ; RD(x) ; RD(y) ; RD(z) ; if(ismst[x][y]){ ans = ans + mst + min((ll)z , NMIN[x][y]) - Map[x][y]; } else ans = ans + mst ; } printf("%.4f\n",1.0 * ans / fk) ; } int main() { while(cin >> n >> m , (n + m))solve() ; return 0 ; }