标签:AC ace nbsp mes amp scan ret 估计 set
题意:
一棵生成树的苗条度被定义为最长边与最小边的差。
给出一个图,求其中生成树的最小苗条度。
思路:
最开始想用二分,始终想不到二分终止的条件,所以尝试暴力枚举最小边的长度,然后就AC了。
粗略估计最大规模为1e8,用时2873ms,卡着时间过。
一个不明显的优化是枚举输入的每一条边。
代码:
1 #include <stdio.h> 2 #include <string.h> 3 #include <algorithm> 4 using namespace std; 5 6 const int inf = 0x3f3f3f3f; 7 8 int mp[105][105]; 9 bool vis[105]; 10 int d[105]; 11 12 int prim(int n,int lim) 13 { 14 memset(vis,0,sizeof(vis)); 15 memset(d,inf,sizeof(d)); 16 17 vis[1] = 1; 18 d[1] = 0; 19 20 int mx = 0,mn = inf; 21 22 for (int i = 2;i <= n;i++) 23 { 24 if (mp[1][i] >= lim) d[i] = mp[1][i]; 25 } 26 27 for (int i = 0;i < n - 1;i++) 28 { 29 //printf("2333\n"); 30 31 int x,dis = inf; 32 33 for (int j = 1;j <= n;j++) 34 { 35 if (!vis[j] && d[j] < dis && d[j] >= lim) 36 { 37 dis = d[j]; 38 x = j; 39 } 40 } 41 42 if (dis == inf) return -1; 43 44 vis[x] = 1; 45 46 mx = max(mx,dis); 47 mn = min(mn,dis); 48 49 for (int j = 1;j <= n;j++) 50 { 51 if (!vis[j] && mp[x][j] < d[j] && mp[x][j] >= lim) 52 { 53 d[j] = mp[x][j]; 54 } 55 } 56 } 57 58 return mx - mn; 59 } 60 61 int main() 62 { 63 int n,m; 64 65 while (scanf("%d%d",&n,&m) != EOF) 66 { 67 if (n == 0 && m == 0) break; 68 69 memset(mp,inf,sizeof(mp)); 70 71 int mxl = 0,mnl = inf; 72 73 for (int i = 0;i < m;i++) 74 { 75 int a,b,c; 76 77 scanf("%d%d%d",&a,&b,&c); 78 79 mp[a][b] = mp[b][a] = c; 80 81 mxl = max(mxl,c); 82 mnl = min(mnl,c); 83 } 84 85 int ans = prim(n,mnl); 86 87 if (ans == -1) printf("-1\n"); 88 else 89 { 90 for (int i = mnl;i <= mxl;i++) 91 { 92 int tmp = prim(n,i); 93 94 if (tmp == -1) break; 95 else ans = min(ans,tmp); 96 } 97 98 printf("%d\n",ans); 99 } 100 } 101 102 return 0; 103 }
标签:AC ace nbsp mes amp scan ret 估计 set
原文地址:https://www.cnblogs.com/kickit/p/8808998.html