• 题解 CF1095F 【Make It Connected】


    题目链接

    Solution CF1095F Make It Connected

    题目大意:给定 (n) 个点,每个点有一个点权 (a_i),在 (i,j) 之间连边的代价为 (a_i + a_j)。除此之外,还给定了额外 (m) 条边。求最小代价使得原图联通。

    贪心,最小生成树


    分析:首先考虑 (m=0) 的做法

    我们直接贪心,选取 (a) 最小的点作为中心,建出一个菊花图,这样一定是最优的。

    证明考虑归纳法,类似于 Prim 算法的思想

    对于 (n = 2) 的情况显然

    对于 (n > 2),前 (n - 1) 个点已经形成了一棵生成树,我们就要把当前点接到树上。当前点的点权是不变的,我们肯定贪心去选树上点权最小的点。

    这样找出一棵生成树之后,我们再把 (m) 条边加入,一起跑最小生成树就可以了

    #include <cstdio>
    #include <cctype>
    #include <vector>
    #include <algorithm>
    using namespace std;
    typedef long long ll;
    constexpr int maxn = 2e5 + 100;
    typedef long long ll;
    struct IO{//-std=c++11,with cstdio and cctype
    	private:
    		static constexpr int ibufsiz = 1 << 20;
    		char ibuf[ibufsiz + 1],*inow = ibuf,*ied = ibuf;
    		static constexpr int obufsiz = 1 << 20;
    		char obuf[obufsiz + 1],*onow = obuf;
    		const char *oed = obuf + obufsiz;
    	public:
    		inline char getchar(){
    			#ifndef ONLINE_JUDGE
    				return ::getchar();
    			#else
    				if(inow == ied){
    					ied = ibuf + sizeof(char) * fread(ibuf,sizeof(char),ibufsiz,stdin);
    					*ied = '';
    					inow = ibuf;
    				}
    				return *inow++;
    			#endif
    		}
    		template<typename T>
    		inline void read(T &x){
    			static bool flg;flg = 0;
    			x = 0;char c = getchar();
    			while(!isdigit(c))flg = c == '-' ? 1 : flg,c = getchar();
    			while(isdigit(c))x = x * 10 + c - '0',c = getchar();
    			if(flg)x = -x;
    		}
    		template <typename T,typename ...Y>
    		inline void read(T &x,Y&... X){read(x);read(X...);}
    		inline int readi(){static int res;read(res);return res;}
    		inline long long readll(){static long long res;read(res);return res;}
    		
    		inline void flush(){
    			fwrite(obuf,sizeof(char),onow - obuf,stdout);
    			fflush(stdout);
    			onow = obuf;
    		}
    		inline void putchar(char c){
    			#ifndef ONLINE_JUDGE
    				::putchar(c);
    			#else
    				*onow++ = c;
    				if(onow == oed){
    					fwrite(obuf,sizeof(char),obufsiz,stdout);
    					onow = obuf;
    				}
    			#endif
    		}
    		template <typename T>
    		inline void write(T x,char split = ''){
    			static unsigned char buf[64];
    			if(x < 0)putchar('-'),x = -x;
    			int p = 0;
    			do{
    				buf[++p] = x % 10;
    				x /= 10;
    			}while(x);
    			for(int i = p;i >= 1;i--)putchar(buf[i] + '0');
    			if(split != '')putchar(split);
    		}
    		inline void lf(){putchar('
    ');}
    		~IO(){
    			fwrite(obuf,sizeof(char),onow - obuf,stdout);
    		}
    }io;
    
    struct edge{int u,v;ll d;};
    vector<edge> edges;
    int n,m;
    ll v[maxn];
    namespace mset{
    	int f[maxn];
    	inline void init(){for(int i = 1;i <= n;i++)f[i] = i;}
    	inline int find(const int x){return x == f[x] ? x : f[x] = find(f[x]);}
    	inline void merge(const int a,const int b){
    		const int x = find(a),y = find(b);
    		f[x] = y;
    	}
    }
    ll ans;
    inline void kruskal(){
    	mset::init();
    	sort(edges.begin(),edges.end(),[](const edge &a,const edge &b){
    		return a.d < b.d;
    	});
    	for(auto e : edges){
    		if(mset::find(e.u) == mset::find(e.v))continue;
    		ans += e.d;
    		mset::merge(e.u,e.v);
    	}
    }
    int p = 1;
    int main(){
    	io.read(n,m);
    	for(int i = 1;i <= n;i++)io.read(v[i]);
    	for(int i = 1;i <= n;i++)
    		if(v[i] < v[p])p = i;
    	for(int i = 1;i <= n;i++)
    		if(i != p)edges.push_back(edge{i,p,v[i] + v[p]});
    	for(int u,v,i = 1;i <= m;i++){
    		io.read(u,v);const ll d = io.readll();
    		edges.push_back(edge{u,v,d});
    	}
    	kruskal();
    	io.write(ans,'
    ');
    	return 0;
    }
    
  • 相关阅读:
    博弈论《《转》》
    HDU 2509 Be the Winner
    SORT排序。。
    HDU 356 SNim
    博弈
    KM算法。《转载》以后看。
    jmeter(28)逻辑控制器 之 交替控制器
    jmeter(30)逻辑控制器 之 Switch Controller 暂时不写!
    jmeter(29)逻辑控制器 之 吞吐量控制器
    Shell一个文件并等待完成
  • 原文地址:https://www.cnblogs.com/colazcy/p/14115467.html
Copyright © 2020-2023  润新知