先求最小生成树,然后dfs求生成树的最小替代边。
#include <iostream> #include <cstdio> #include <cstring> using namespace std; const int maxn=3e3+9,inf=1e9; int n,m; int dist[maxn],g[maxn][maxn],tree[maxn][maxn]; int f[maxn][maxn]; struct { int head[maxn],lon; struct { int next,to,w; }e[maxn*maxn<<1]; void clear() { memset(head,-1,sizeof(head)); lon=0; } void add(int from,int to,int w=0) { e[++lon].to=to; e[lon].w=w; e[lon].next=head[from]; head[from]=lon; } }edge[2]; double prim() { int key[maxn],from[maxn]; bool visit[maxn]; memset(visit,0,sizeof(visit)); memset(key,50,sizeof(key)); memset(f,0,sizeof(f)); memset(tree,0,sizeof(tree)); visit[1]=1; for(int k=edge[0].head[1];k!=-1;k=edge[0].e[k].next) { int u=edge[0].e[k].to; key[u]=edge[0].e[k].w; from[u]=1; } double ans=0; for(int p=2,u;p<=n;p++) { int now=inf; for(int i=1;i<=n;i++) if(!visit[i]&&key[i]<now) now=key[i],u=i; edge[1].add(from[u],u); edge[1].add(u,from[u]); tree[from[u]][u]=tree[u][from[u]]=key[u]; for(int i=1;i<=n;i++) if(visit[i]) f[u][i]=f[i][u]=max(f[u][i],key[u]); ans+=key[u]; visit[u]=1; for(int k=edge[0].head[u];k!=-1;k=edge[0].e[k].next) { int v=edge[0].e[k].to; if(!visit[v]&&key[v]>edge[0].e[k].w) { from[v]=u; key[v]=edge[0].e[k].w; } } } return ans; } int dfs(int now,int from) { int mmin=dist[now]; for(int k=edge[1].head[now];k!=-1;k=edge[1].e[k].next) { int u=edge[1].e[k].to; if(u==from) continue; mmin=min(dfs(u,now),mmin); } g[now][from]=g[from][now]=min(g[now][from],mmin); return mmin; } int main() { while(scanf("%d %d",&n,&m),n||m) { edge[0].clear(); edge[1].clear(); for(int i=1,from,to,w;i<=m;i++) { scanf("%d %d %d",&from,&to,&w); from++,to++; edge[0].add(from,to,w); edge[0].add(to,from,w); } double mst=prim(); memset(g,50,sizeof(g)); for(int i=1;i<=n;i++) { for(int j=1;j<=n;j++) dist[j]=inf; for(int k=edge[0].head[i];k!=-1;k=edge[0].e[k].next) { int u=edge[0].e[k].to; dist[u]=edge[0].e[k].w; } for(int k=edge[1].head[i];k!=-1;k=edge[1].e[k].next) { int u=edge[1].e[k].to; dist[u]=inf; } dfs(i,0); } double ans=0; int q; scanf("%d",&q); for(int i=1,from,to,w;i<=q;i++) { scanf("%d %d %d",&from,&to,&w); from++,to++; if(tree[from][to]==0) { // ans+=mst; int tmp=min(f[from][to],w); ans+=mst+tmp-f[from][to]; } else { int tmp=min(w,g[from][to]); ans+=mst-tree[from][to]+tmp; } } printf("%.4f\n",ans/q); } return 0; }