zoukankan      html  css  js  c++  java
  • [JSOI2008]巨额奖金(最小生成树计数)

    基于kruscal的贪心 可以有如下推论:两个不同的最小生成树所用的的相同边权的边的数量相同。

    可以做这样的理解:当进行到选第K大的边时,联通快数是一定的所以的、一定需要K- 1个该权值边 (不知道对不对 欢迎TuneProverbs指正)

    SB没想好怎么存水体写半天。。。。。。。

    我是SB
      1 #include <cstdio>
      2 #include <vector>
      3 #include <cstring>
      4 #include <iostream>
      5 #include <algorithm>
      6 using namespace std;
      7 const int N = 1500;typedef long long LL;
      8 vector<int> v[N];
      9 vector<int>::iterator it, ptr;
     10 int n, m, p[N], cnt[N], cc, r[N];
     11 LL ans;
     12 bool vis[N], cantvisit[N], noans;
     13 struct Q {
     14     int x, y, w, num;
     15     inline bool operator < (const Q & a) const {
     16         return w < a.w;
     17     }
     18 }e[N];
     19 inline int F (int x) { return p[x] == x ? x : p[x] = F (p[x]); }
     20 void ksc ()
     21 {
     22     for (int i = 1; i <= n; i ++)
     23         p[i] = i;
     24     sort (e + 1, e + 1 + m);
     25     for (int i = 1; i <= m; i ++)
     26         if (F (e[i].x) != F (e[i].y))
     27         {
     28             p[F (e[i].x)] = F (e[i].y);
     29             ans += e[i].w;
     30             int j (0);
     31             for (int j = 1; j <= cc; j ++)
     32                 if (r[j] == e[i].w)
     33                     cnt[j] ++;
     34         }
     35     for (int i = 2; i <= n; i ++)
     36         if (F (i) != F (i - 1))
     37             noans = true;
     38     //for (int i = 1; i <= 5; i ++)
     39     //    printf ("%d\n", cnt[i]);
     40     //printf ("%d\n", ans);
     41 }
     42 bool ck ()
     43 {
     44     for (int i = 1; i <= n; i ++)
     45         p[i] = i;
     46     sort (e + 1, e + 1 + m);
     47     LL z (0);
     48     for (int i = 1; i <= m; i ++)
     49     {
     50         if (cantvisit[e[i].num]) continue;
     51         if (F (e[i].x) != F (e[i].y))
     52         {
     53             p[F (e[i].x)] = F (e[i].y);
     54             z += e[i].w;
     55         }
     56     }
     57     //printf ("%d\n", z);
     58     return z == ans;
     59 }
     60 inline int calc (int j)
     61 {
     62     int z (0);
     63     for (; j; j -= j & -j) z ++;
     64     return z;
     65 }
     66 int main ()
     67 {
     68     scanf ("%d%d", &n, &m);
     69     for (int i = 1; i <= m; i ++)
     70         scanf ("%d%d%d", &e[i].x, &e[i].y, &e[i].w), e[i].num = i;
     71     for (int i = 1; i <= m; i ++)
     72     {
     73         if (vis[i]) continue;
     74         cc ++;
     75         r[cc] = e[i].w;
     76         v[cc].push_back (i);
     77         for (int j = i + 1; j <= m; j ++)
     78             if (e[j].w == e[i].w)
     79             {
     80                 vis[j] = true;
     81                 v[cc].push_back (j);
     82             }
     83     }
     84     ksc ();
     85     if (noans == true)
     86     {
     87         puts ("0");
     88         return 0;
     89     }
     90     int z (1);
     91     for (int j = 1; j <= cc; j ++)
     92     {
     93         int tmp (0);
     94         //printf ("*%d\n", v[j].size ());
     95         for (int i = 0; i < (1 << v[j].size ()); i ++)
     96         {
     97             if (calc (i) == cnt[j])
     98             {
     99                 int k (0);
    100                 for (ptr = v[j].begin (); ptr != v[j].end (); ptr ++, k ++)
    101                     if ((i >> k) & 1)
    102                         ;
    103                     else
    104                         cantvisit[*ptr] = true;
    105                 //for (int i = 1; i <= m; i ++)
    106                 //    printf ("%d", cantvisit[i]);puts ("");
    107                 int t (0);
    108                 if (t = ck ())
    109                     tmp ++;
    110                 memset (cantvisit, 0, sizeof cantvisit);
    111             }
    112         }
    113         //printf ("%d\n", tmp);
    114         if (tmp != 0)
    115             z = ((long long)z * tmp) % 31011;
    116     }
    117     printf ("%d\n", z);
    118     return 0;
    119 }
  • 相关阅读:
    hdu 1250 简单大整数加法
    hdu 3594 强连通好题仙人掌图,对自己的tarjan模板改下用这个
    hdu 1568关于斐波那契数列的公式及其思维技巧
    hdu 1245 Saving James Bond 策画几何+最短路 最短路求步数最少的路径
    关于c对文件的操作
    hdu 1829 带权并查集的运用类似于食物链但是更简单些
    hdu 1716 深搜dfs
    hdu 1713求分数的最小公倍数
    1268 和为K的组合 Meet in mid二分思路
    1163 最高的奖励 贪心 + 并查集
  • 原文地址:https://www.cnblogs.com/tellmewtf/p/2891431.html
Copyright © 2011-2022 走看看