uvalive 3887 Slim Span

题意:

一棵生成树的苗条度被定义为最长边与最小边的差。

给出一个图,求其中生成树的最小苗条度。

思路:

最开始想用二分,始终想不到二分终止的条件,所以尝试暴力枚举最小边的长度,然后就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 }

 

posted @ 2018-04-12 17:10  qrfkickit  阅读(210)  评论(0编辑  收藏  举报