• [POI2013]Tower Defense Game


    题目大意:
      一个$n(nle5 imes10^5)$个点$m(mle10^6)$条边的无向图,边权全为$1$,满足若一个标记点能覆盖与其距离不超过$1$的点,从中选取不超过$k$个点能将整张图覆盖。问若一个标记点能覆盖与其距离不超过$2$的点,求构造一种选取点数不超过$k$的方案将整张图覆盖。

    思路:
      贪心,每次选取没有覆盖的点作为标记点,并更新覆盖点的和。选取一个点后增加的覆盖范围一定完全包含原来覆盖这个点的标记点的覆盖范围,因此方案一定更优。

     1 #include<cstdio>
     2 #include<cctype>
     3 inline int getint() {
     4     register char ch;
     5     while(!isdigit(ch=getchar()));
     6     register int x=ch^'0';
     7     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     8     return x;
     9 }
    10 const int N=5e5+1,M=2e6+1;
    11 bool b[N],vis[N];
    12 int h[N],ans[N];
    13 struct Edge {
    14     int to,next;
    15 };
    16 Edge e[M];
    17 inline void add_edge(const int &u,const int &v) {
    18     e[++h[0]]=(Edge){v,h[u]};h[u]=h[0];
    19     e[++h[0]]=(Edge){u,h[v]};h[v]=h[0];
    20 }
    21 int main() {
    22     const int n=getint(),m=getint(),k=getint();
    23     for(register int i=0;i<m;i++) {
    24         add_edge(getint(),getint());
    25     }
    26     for(register int x=1;x<=n;x++) {
    27         if(vis[x]) continue;
    28         ans[++ans[0]]=x;
    29         vis[x]=b[x]=true;
    30         for(register int i=h[x];i;i=e[i].next) {
    31             const int &y=e[i].to;
    32             if(b[y]) continue;
    33             vis[y]=true;
    34             for(register int i=h[y];i;i=e[i].next) {
    35                 const int &z=e[i].to;
    36                 vis[z]=true;
    37             }
    38         }
    39     }
    40     printf("%d
    ",ans[0]);
    41     for(register int i=1;i<=ans[0];i++) {
    42         printf("%d%c",ans[i]," 
    "[i==ans[0]]);
    43     }
    44     return 0;
    45 }
  • 相关阅读:
    Android_AyscnTask
    Android_handler
    Android_网络操作
    Android_网络基础
    Android_Fragment
    Android_activity 生命周期
    Android-Dialog
    android_menu
    Android-约束布局
    andorid_相对布局小练习
  • 原文地址:https://www.cnblogs.com/skylee03/p/8676472.html
Copyright © 2020-2023  润新知