正如题目描述,这道题是求第二小生成树。嗯,这里的第二小生成树是指除了与某个第一小的生成树不完全相同的生成树。换而言之,就是说如果有两棵生成树能够满足最小,那么第二小仍然和第一小是一样的(比如样例)。为什么我一直要说明这个问题?因为还有另外一种次小生成树,是指 生成树 中除去所有最小生成树的 最小的生成树 。 当然那道题难度比这道大多,我们不扯远了=  =。
      先用克鲁斯卡尔算出最小生成树,那么可以证明第二小生成树必定不包含最小生成树中的某条边(显而易见,否则它就是这棵树了),那么依次枚举最小生成树的边,去掉,再计算二小生成树。这么多中最小的就是我们的结果了。但是注意一个牛X的剪枝,我当时就是没加过不了,就是计算二小生成树的时候,如果当前费用已经超过我们正在更新的最小费用,就立刻终止这次,因为再算下去最小费用也不会更新了。
      丑陋源代码:

  1  #include < iostream >
  2  #include < algorithm >
  3  using   namespace  std;
  4 
  5  #define  MAXINT 2147483647
  6 
  7  struct  Line
  8  {
  9       int  x,y;
 10       int  v;
 11  };
 12 
 13  Line line[ 250001 ];
 14  int  f[ 501 ];
 15  int  re[ 501 ],pos,num,se;
 16  int  cnt;
 17  int  n,m;
 18 
 19  bool  cmp( const  Line & a, const  Line & b)
 20  {
 21       return  a.v < b.v;
 22  }
 23 
 24  int  find( int  x)
 25  {
 26       if  (f[x] == x)
 27           return  x;
 28       int  t = find(f[x]);
 29      f[x] = t;
 30       return  t;
 31  }
 32 
 33  int  ke1()
 34  {
 35       for  ( int  i = 1 ;i <= n;i ++ )
 36          f[i] = i;
 37       int  fei = 0 ;
 38      cnt = 0 ;
 39       for  ( int  i = 1 ;i <= m;i ++ )
 40      {
 41           int  t1 = find(line[i].x),t2 = find(line[i].y);
 42           if  (t1 != t2)
 43          {
 44              cnt ++ ;
 45              f[t2] = t1;
 46              fei += line[i].v;
 47              re[ ++ num] = i;
 48          }
 49      }
 50       return  fei;
 51  }
 52 
 53  int  ke()
 54  {
 55       for  ( int  i = 1 ;i <= n;i ++ )
 56          f[i] = i;
 57       int  fei = 0 ;
 58      cnt = 0 ;
 59       for  ( int  i = 1 ;i <= m;i ++ )
 60           if  (i != re[pos])
 61          {
 62               int  t1 = find(line[i].x),t2 = find(line[i].y);
 63               if  (t1 != t2)
 64              {
 65                  cnt ++ ;
 66                  f[t2] = t1;
 67                  fei += line[i].v;
 68              }
 69               if  (fei > se)  return  MAXINT;
 70          }
 71       return  fei;
 72  }
 73 
 74  void  work()
 75  {
 76       int  fei = ke1();
 77       if  (cnt != n - 1 )
 78      {
 79          printf( " Cost: -1\nCost: -1\n " );
 80           return ;
 81      }
 82      printf( " Cost: %d\n " ,fei);
 83      se = MAXINT;
 84       for  ( int  i = 1 ;i <= num;i ++ )
 85      {
 86          pos = i;
 87           int  t = ke();
 88           if  (cnt == n - 1 )
 89               if  (t < se) se = t;
 90      }
 91       if  (se == MAXINT)
 92          printf( " Cost: -1\n " );
 93       else
 94          printf( " Cost: %d\n " ,se);
 95  }
 96 
 97  int  main()
 98  {
 99      scanf( " %d%d " , & n, & m);
100       for  ( int  i = 1 ;i <= m;i ++ )
101          scanf( " %d%d%d " , & line[i].x, & line[i].y, & line[i].v);
102      sort(line + 1 ,line + 1 + m,cmp);
103      work();
104  }