1. 程式人生 > >uvalive 3887 Slim Span

uvalive 3887 Slim Span

ons \n namespace main uvalive size 時間 int 暴力

題意:

一棵生成樹的苗條度被定義為最長邊與最小邊的差。

給出一個圖,求其中生成樹的最小苗條度。

思路:

最開始想用二分,始終想不到二分終止的條件,所以嘗試暴力枚舉最小邊的長度,然後就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 }

uvalive 3887 Slim Span