• BZOJ 2521: [Shoi2010]最小生成树


    2521: [Shoi2010]最小生成树

    Time Limit: 10 Sec  Memory Limit: 128 MB
    Submit: 445  Solved: 262
    [Submit][Status][Discuss]

    Description

    Secsa最近对最小生成树问题特别感兴趣。他已经知道如果要去求出一个n个点、m条边的无向图的最小生成树有一个Krustal算法和另一个Prim的算法。另外,他还知道,某一个图可能有多种不同的最小生成树。例如,下面图 3中所示的都是图 2中的无向图的最小生成树:
     
     

    当然啦,这些都不是今天需要你解决的问题。Secsa想知道对于某一条无向图中的边AB,至少需要多少代价可以保证AB边在这个无向图的最小生成树中。为了使得AB边一定在最小生成树中,你可以对这个无向图进行操作,一次单独的操作是指:先选择一条图中的边 P1P2,再把图中除了这条边以外的边,每一条的权值都减少1。如图 4所示就是一次这样的操作:

    Input

    输入文件的第一行有3个正整数n、m、Lab分别表示无向图中的点数、边数、必须要在最小生成树中出现的AB边的标号。
    接下来m行依次描述标号为1,2,3…m的无向边,每行描述一条边。每个描述包含3个整数x、y、d,表示这条边连接着标号为x、y的点,且这条边的权值为d。
    输入文件保证1<=x,y<=N,x不等于y,且输入数据保证这个无向图一定是一个连通图。

    Output

    输出文件只有一行,这行只有一个整数,即,使得标号为Lab边一定出现最小生成树中的最少操作次数。

    Sample Input

    4 6 1
    1 2 2
    1 3 2
    1 4 3
    2 3 2
    2 4 4
    3 4 5

    Sample Output

    1

    HINT

    第1个样例就是问题描述中的例子。


    1<=n<=500,1<=M<=800,1<=D<10^6

    Source

    [Submit][Status][Discuss]

    题目中的操作——将除这条边外所有其他边的权值全部+1——就是忽悠人的,等价于将这条边的权值+1。

    利用Kruskal算法的思想,如果将所有边按照权值从小到大排序后,排在指定边之前(包括和指定边权值相同)的边能使得指定边的两点联通,则指定边一定不会被选中。将一条边从指定边之前移走的最小代价就是使得其变得严格大于指定边,插值是$Val_{id}-Val_{i}+1$。把代价作为容量,跑最小割即可。

      1 #include <cstdio>
      2 #include <cstring>
      3 
      4 inline char nextChar(void)
      5 {
      6     static const int siz = 1 << 20;
      7     
      8     static char buf[siz];
      9     static char *hd = buf + siz;
     10     static char *tl = buf + siz;
     11     
     12     if (hd == tl)
     13         fread(hd = buf, 1, siz, stdin);
     14     
     15     return *hd++;
     16 }
     17 
     18 inline int nextInt(void)
     19 {
     20     register int ret = 0;
     21     register bool neg = false;
     22     register char bit = nextChar();
     23     
     24     for (; bit < 48; bit = nextChar());
     25         if (bit == '-')neg ^= true;
     26     
     27     for (; bit > 47; bit = nextChar())
     28         ret = ret * 10 + bit - '0';
     29     
     30     return neg ? -ret : ret;
     31 }
     32 
     33 const int siz = 2005;
     34 const int edg = 2e6 + 5;
     35 const int inf = 2e9 + 7;
     36 
     37 int n, m, id, s, t;
     38 
     39 struct edge
     40 {
     41     int x, y, w;
     42 }e[edg];
     43 
     44 int hd[siz], to[edg], nt[edg], fl[edg], tot;
     45 
     46 inline void add(int u, int v, int f)
     47 {
     48     nt[tot] = hd[u]; to[tot] = v; fl[tot] = f; hd[u] = tot++;
     49     nt[tot] = hd[v]; to[tot] = u; fl[tot] = 0; hd[v] = tot++;
     50 }
     51 
     52 int dep[siz];
     53 
     54 inline bool bfs(void)
     55 {
     56     static int que[siz];
     57     static int head, tail;
     58     
     59     memset(dep, 0, sizeof(dep));
     60     
     61     que[head = 0] = s, tail = dep[s] = 1;
     62     
     63     while (head != tail)
     64     {
     65         int u = que[head++], v;
     66         
     67         for (int i = hd[u]; ~i; i = nt[i])
     68             if (!dep[v = to[i]] && fl[i])
     69                 dep[que[tail++] = v] = dep[u] + 1;
     70     }
     71     
     72     return dep[t];
     73 }
     74 
     75 int cur[siz];
     76 
     77 inline int min(int a, int b)
     78 {
     79     return a < b ? a : b;
     80 }
     81 
     82 int dfs(int u, int f)
     83 {
     84     if (!f || u == t)
     85         return f;
     86     
     87     int used = 0, flow, v;
     88     
     89     for (int i = cur[u]; ~i; i = nt[i])
     90         if (dep[v = to[i]] == dep[u] + 1 && fl[i])
     91         {
     92             flow = dfs(v, min(fl[i], f - used));
     93             
     94             used += flow;
     95             fl[i] -= flow;
     96             fl[i^1] += flow;
     97             
     98             if (fl[i])
     99                 cur[u] = i;
    100             
    101             if (used == f)
    102                 return f;
    103         }
    104     
    105     if (!used)
    106         dep[u] = 0;
    107     
    108     return used;
    109 }
    110 
    111 inline int minCut(void)
    112 {
    113     int minCut = 0, newFlow;
    114     
    115     while (bfs())
    116     {
    117         memcpy(cur, hd, sizeof(hd));
    118         
    119         while (newFlow = dfs(s, inf))
    120             minCut += newFlow;
    121     }
    122     
    123     return minCut;
    124 }
    125 
    126 signed main(void)
    127 {
    128     n = nextInt();
    129     m = nextInt();
    130     
    131     id = nextInt();
    132     
    133     for (int i = 1; i <= m; ++i)
    134     {
    135         e[i].x = nextInt();
    136         e[i].y = nextInt();
    137         e[i].w = nextInt();
    138     }
    139     
    140     s = e[id].x;
    141     t = e[id].y;
    142     
    143     int lim = e[id].w;
    144     
    145     memset(hd, -1, sizeof(hd));
    146     
    147     for (int i = 1; i <= m; ++i)
    148         if (e[i].w <= lim && i != id)
    149             add(e[i].x, e[i].y, lim + 1 - e[i].w),
    150             add(e[i].y, e[i].x, lim + 1 - e[i].w);
    151         
    152     printf("%d
    ", minCut());
    153 }

    @Author: YouSiki

  • 相关阅读:
    samtools获取uniq reads
    NSDate的比较
    UIViewAlertForUnsatisfiableConstraints布局问题
    如何将网页保存为pdf
    使用Carthage管理iOS依赖库
    输出格式
    解决问题思路
    重:将好用的控件,上次github,
    解决CocoaPods慢的小技巧
    swift开发笔记28 CoreML
  • 原文地址:https://www.cnblogs.com/yousiki/p/6337599.html
Copyright © 2020-2023  润新知