给你一个完全图,让你在上面找到一颗最小树,然后问破坏这个最小树的某一条边后用其他边连接(要求最小)成新的树,然后输出破坏每一条边后最小树中最大的那个.
思路:
先跑出一颗最小树,然后枚举树上的每一条边,当这条边被删除的时候,生成树就被分成了两个集合,然后找到一条最小的能让两个集合相通的替代边,最后输出最大的那个(树形dp优化),下面是我的ac记录
想法错了 求的次小树 WA
Kruskal + 并查集优化 暴力枚举 TLE
Kruskal + 树形DP TLE
Prim + 树形DP AC
哎,这个题目时间卡的太紧了, 这个题目非得强调K是解决稀疏图的,P是解决稠密图的...
(下面的Prim之前没用过,之前用的是K,所以直接百度了个模板,然后写成结构体了,所以整个代码有点乱因为要配合百度来的Prim,自己懒啊,不想再看Prim了,只是记下他的模板了,以后遇到卡稠密图的题再粘过来.)
#include<stdio.h> #include<string.h> #include<math.h> #define N (1000 + 100) #define inf 100000000 typedef struct { int x ,y; }NODE; typedef struct { int a ,b; double dis; }EDGE; typedef struct { int to ,next; }STAR; NODE node[N]; EDGE edge[N*N/2]; STAR E[N*2]; int list[N] ,tot; double map[N][N]; double dp[N][N]; bool camp(EDGE a ,EDGE b) { return a.dis < b.dis; } void add(int a, int b) { E[++tot].to = b; E[tot].next = list[a]; list[a] = tot; E[++tot].to = a; E[tot].next = list[b]; list[b] = tot; } double maxx(double a ,double b) { return a > b ? a : b; } double minn(double a ,double b) { return a < b ? a : b; } double q_dis(double x1 ,double y1 ,double x2 ,double y2) { double x = x1 - x2; double y = y1 - y2; return sqrt(x * x + y * y); } double dfs(int p ,int s ,int f) { double now = inf; for(int k = list[s] ;k ;k = E[k].next) { int to = E[k].to; if(to == f) continue; double tmp = dfs(p ,to ,s); now = minn(now ,tmp); dp[s][to] = dp[to][s] = minn(dp[s][to] ,tmp); } if(p != f) now = minn(now ,map[p][s]); return now; } struct PRIM //从0开始用 { double d[N];int vis[N]; bool mp[N][N]; //标记最小生成树上的边 double ans;//最小树 int n;//点的个数 记得初始化 *** double dis[N][N]; // 距离 记得初始化 ***** void prim() { for(int i=0;i<n;i++) { vis[i]=0; d[i]=dis[0][i]; } vis[0]=-1; ans=0; memset(mp,0,sizeof(mp)); for(int i=1;i<n;i++) { double Min= inf; int node=-1; for(int j=0;j<n;j++) { if(vis[j]!=-1 && d[j]<Min) { node=j; Min=d[j]; } } ans+=Min; mp[vis[node]][node]=mp[node][vis[node]]=1; add(vis[node],node); // 建树 vis[node]=-1; for(int j=0;j<n;j++) { if(vis[j]!=-1 && d[j]>dis[node][j]) { vis[j]=node; d[j]=dis[node][j]; } } } } }P; int main () { int t ,i ,j ,n; double pre; scanf("%d" ,&t); while(t --) { scanf("%d %lf" ,&n ,&pre); for(i = 0 ;i < n ;i ++) scanf("%d %d" ,&node[i].x ,&node[i].y); int tmp = 0; for(i = 0 ;i < n ;i ++) { for(j = i ;j < n ;j ++) { map[j][i] = map[i][j] = q_dis(node[i].x ,node[i].y ,node[j].x ,node[j].y); P.dis[i][j] = P.dis[j][i] = map[i][j]; edge[++tmp].a = i; edge[tmp].b = j; edge[tmp].dis = map[i][j]; dp[i][j] = dp[j][i] = inf; } } P.n = n; memset(list ,0 ,sizeof(list)); tot = 1; P.prim(); for(i = 1 ;i <= n ;i ++) dfs(i ,i ,-1); double T_sum = P.ans; double ans = T_sum; for(i = 1 ;i < n ;i ++) for(j = i + 1 ;j < n ;j ++) if(P.mp[i][j]) ans = maxx(ans ,T_sum - map[i][j] + dp[i][j]); printf("%.2lf " ,ans * pre); } return 0; }