• hihoCoder 1160 攻城略地


    原图可能有多个连通分量,先DFS找出每个连通分量中最小节点,这些必然是要攻占的城市。

    设 n 为节点数, m 为边数, cnt 为初始连通分量数,在剩下的边数不小于 m - (n - cnt) 的时候,图的连通性是不变的,也就是在这之前可以适当策略删边保持结果不变。

    当边数小于等于 m - (n - cnt) 时,每删一条边,必然多一个连通分量,我们总可以做到让多出来这个连通分量的最小结点 是所有节点中除去已经选定的那些节点之外的最小节点,所以这时对节点以权值排序从小往大记到删够边数为止。

     1 #include<stdio.h>
     2 #include<string.h>
     3 #include<stdlib.h>
     4 #include<algorithm>
     5 typedef long long LL;
     6 const int maxn = 1111111;
     7 const int maxm = 2111111;
     8 int n, m, k;
     9 int fst[maxn];
    10 int wt[maxn];
    11 int vis[maxn];
    12 int nex[maxm], w[maxm], ntp;
    13 void AddEdge(int a, int b)
    14 {
    15     nex[ntp] = fst[a];
    16     w[ntp] = b;
    17     fst[a] = ntp ++;
    18 }
    19 inline int min(int a, int b){return a < b ? a : b;}
    20 void DFS(int nd, int &okcity)
    21 {
    22     if(vis[nd]) return;
    23     vis[nd] = true;
    24     if(okcity == -1 || wt[nd] < wt[okcity])
    25         okcity = nd;
    26     for(int i = fst[nd]; i != -1; i = nex[i])
    27         DFS(w[i], okcity);
    28 }
    29 int main()
    30 {
    31     int t, ca;
    32     for(scanf("%d", &t), ca = 1; ca <= t; ca ++)
    33     {
    34         int a, b;
    35         scanf("%d%d%d", &n, &m, &k);
    36         memset(fst, -1, sizeof(fst));
    37         memset(vis, 0, sizeof(vis));
    38         for(int i = 1; i <= n; i ++)
    39             scanf("%d", &wt[i]);
    40         ntp = 0;
    41         for(int i = 0; i < m; i ++)
    42         {
    43             scanf("%d%d", &a, &b);
    44             AddEdge(a, b);
    45             AddEdge(b, a);
    46         }
    47         int cnt = 0;
    48         LL ans = 0;
    49         for(int i = 1; i <= n; i ++)
    50         {
    51             int okcity = -1;
    52             DFS(i, okcity);
    53             if(okcity != -1)
    54                 cnt ++, ans += wt[okcity], vis[okcity] = 2;
    55         }
    56 
    57         if((k -= m - (n - cnt)) > 0)
    58         {
    59             int i, j;
    60             for(i = 1, j = 1; i <= n; i ++)
    61                 if(vis[i] != 2) wt[j ++] = wt[i];
    62             std::sort(wt + 1, wt + j);
    63             for(int i = 1; k > 0 && i <= j; i ++)
    64                 ans += wt[i], k --;
    65         }
    66         printf("Case #%d: %lld
    ", ca, ans);
    67     }
    68     return 0;
    69 }
  • 相关阅读:
    js---选择排序
    js----冒泡排序
    js---快速排序
    js---去重方法(二)
    js---去重方法(一)
    js--进度条
    随机生成6位数验证码
    倒计时
    别踩白块
    贪吃蛇小游戏
  • 原文地址:https://www.cnblogs.com/CSGrandeur/p/4459680.html
Copyright © 2020-2023  润新知