zoukankan      html  css  js  c++  java
  • AT3911 Forest(并查集+贪心)

    满分做法:

    题目概述:连通块联通的最小代价。但本题要求选过的点不能再选,所以要选(2*(tot-1))个点((tot)为连通块个数),这波选点就需要贪心了。

    首先在每个连通块中选出最小权值的点,并把剩下的点全部加到队列里排序,再选出(tot-2)个点即可。判(impossible)就是剩下的够不够(tot-2)个即可。

    这样选的点联通性显然可行(虽然我不会证明),就这样记住就行了吧!

    #include<cstring>
    #include<algorithm>
    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<queue>
    #include<vector>
    using namespace std;
    typedef long long ll;
    const int maxm=100007;
    int n,m;
    int tot;//连通块个数 
    int w[maxm],f[maxm];
    int cnt[maxm];
    vector<int> t,q[maxm];
    ll ans=0;
    int find(int x)
    {
     if(x!=f[x])
     f[x]=find(f[x]);
     return f[x];	
    }
    int main()
    {
     scanf("%d%d",&n,&m);
     for(int i=1;i<=n;i++)
     scanf("%d",&w[i]),f[i]=i;
     for(int i=1;i<=m;i++)
     {
      int x,y;
      scanf("%d%d",&x,&y);
      x++;//编号初始为0,++变1 
      y++;
      int fx=find(x);
      int fy=find(y);
      if(fx!=fy) f[fx]=fy;
     }
     for(int i=1;i<=n;i++)
     {
       int fx=find(i);
       if(!cnt[fx]) cnt[fx]=++tot;
       q[cnt[fx]].push_back(w[i]);
     }
     if(tot==1)//如果只有一个连通块,直接可行
     {
      printf("0
    ");
      return 0; 
     } 
     for(int i=1;i<=tot;i++)
     {
      sort(q[i].begin(),q[i].end());
      ans+=q[i][0];
      for(int j=1;j<q[i].size();j++)
      {
      	t.push_back(q[i][j]);
      }
     }
     if(t.size()<tot-2)
     {
      printf("Impossible
    ");
      return 0;	
     }
     sort(t.begin(),t.end());
     for(int i=0;i<tot-2;i++)
     ans+=t[i];
     printf("%lld
    ",ans);
     return 0;	
    }
    
    
  • 相关阅读:
    JZOJ1495 宝石
    JZOJ1496 页
    jzoj1497. 景点中心
    2019.8.2总结
    学习进度报告2021/3/19
    学习进度报告2021/3/18
    《学会提问》读书笔记2
    学习进度报告2021/3/17
    学习进度报告2021/3/16
    学习进度报告2021/3/15
  • 原文地址:https://www.cnblogs.com/lihan123/p/11673445.html
Copyright © 2011-2022 走看看