• [BZOJ1543] 生成树计数 (Kruskal)


    Description

      给定一个连通的带边权的图(允许自环和重边),求不同的最小生成树个数。两个生成树不同当它们所用的边的序号不同,换句话说,重边算多次。

    Input

      第一行n,m,表示点数和边数(1<=n<=50000,1<=m<=100000) 下接m行,每行3个数k1,k2,w,表示k1和k2之间有一条权值为w 的边。

    Output

      仅一行一个数:生成树个数 mod 1000003(质数)

    Sample Input

    3 5
    1 2 6
    1 2 6
    2 3 6
    3 1 6
    3 3 8

    Sample Output

    5

      注:不会存在5条及5条以上的边,他们的边权是相同的。
      样例解释:
      5棵生成树分别如下(边按输入顺序标号):
      (1,3) (2,3) (1,4) (2,4) (3,4)
      5号边是自环。

    HINT

    Source

      HNOI2009集训Day3

    Solution

      同$BZOJ1016$,感觉如果第一页那题能过,这题也能过。题解依然是我写的。

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 struct edge
     4 {
     5     int u, v, w, x;
     6     inline bool operator< (const edge &rhs) const
     7     {
     8         return x < rhs.x;
     9     }
    10 }e[100005];
    11 struct count
    12 {
    13     int l, r, use;
    14 }g[100005];
    15 int n, m, fa[50005], siz[50005];
    16    
    17 int getfa(int x)
    18 {
    19     return fa[x] == x ? x : getfa(fa[x]);
    20 }
    21    
    22 void link(int u, int v)
    23 {
    24     if(siz[u] > siz[v]) fa[v] = u, siz[u] += siz[v];
    25     else fa[u] = v, siz[v] += siz[u];
    26 }
    27    
    28 bool Kruskal()
    29 {
    30     int cnt = 0, u, v;
    31     for(int i = 1; i <= m; ++i)
    32     {
    33         u = getfa(e[i].u), v = getfa(e[i].v);
    34         if(u != v)
    35         {
    36             link(u, v);
    37             ++g[e[i].w].use;
    38             if(++cnt == n - 1) return true;
    39         }
    40     }
    41     return false;
    42 }
    43    
    44 int DFS(int w, int i, int k)
    45 {
    46     if(k == g[w].use) return 1;
    47     if(i > g[w].r) return 0;
    48     int ans = 0, u = getfa(e[i].u), v = getfa(e[i].v);
    49     if(u != v)
    50     {
    51         link(u, v);
    52         ans = DFS(w, i + 1, k + 1);
    53         fa[u] = u, fa[v] = v;
    54     }
    55     return ans + DFS(w, i + 1, k);
    56 }
    57    
    58 int main()
    59 {
    60     int u, v, w, ans;
    61     cin >> n >> m;
    62     for(int i = 1; i <= n; ++i)
    63         fa[i] = i, siz[i] = 1;
    64     for(int i = 1; i <= m; ++i)
    65     {
    66         cin >> u >> v >> w;
    67         e[i] = (edge){u, v, 0, w};
    68     }
    69     sort(e + 1, e + m + 1);
    70     w = 0;
    71     for(int i = 1; i <= m; ++i)
    72         if(e[i].x == e[i - 1].x) e[i].w = w;
    73         else
    74         {
    75             g[w].r = i - 1;
    76             e[i].w = ++w;
    77             g[w].l = i;
    78         }
    79     g[w].r = m;
    80     ans = Kruskal();
    81     for(int i = 1; i <= n; ++i)
    82         fa[i] = i, siz[i] = 1;
    83     for(int i = 1; i <= w; ++i)
    84     {
    85         ans = ans * DFS(i, g[i].l, 0) % 1000003;
    86         for(int j = g[i].l; j <= g[i].r; ++j)
    87         {
    88             u = getfa(e[j].u), v = getfa(e[j].v);
    89             if(u != v) link(u, v);
    90         }
    91     }
    92     cout << ans << endl;
    93     return 0;
    94 }
    View Code
  • 相关阅读:
    Delphi中TFlowPanel实现滚动条效果
    Delphi组件开发-在窗体标题栏添加按钮(使用MakeObjectInstance(NewWndProc),并处理好多消息)
    减小Delphi的Exe文件大小(11种方法)
    画出太极图
    类似地图的以鼠标为中心缩放图像
    andoid x项目的优化 1
    ICON图标文件解析
    所有语言的Awesome(2)
    获取EIP(汇编语言直接给Delphi变量赋值)
    Qt Windows下链接子系统与入口函数(终结版)(可同时存在main和WinMain函数)
  • 原文地址:https://www.cnblogs.com/CtrlCV/p/5668752.html
Copyright © 2020-2023  润新知