zoukankan      html  css  js  c++  java
  • codeforces 1245D(最小生成树)

    题面链接:https://codeforces.com/problemset/problem/1245/D

    题意大概是给你一些城市的坐标,可以在城市中建立发电站,也可以让某个城市和已经建好发电站的城市连接,保证在这两种操作下使得所有的城市供电,在城市建发电站需要花费Ci,城市a和城市b连接需要花费(|Xa-Xb| + |Ya-Yb| )*(Ka+Kb),求最小的花费让所有城市通电。

    思路:首先建立一个源点,连接各个城市,边权就是建发电站费用Ci,若选择此边则表示是在该城市建了发电站。

               剩下的城市互相按照题意要求建边,建完全图。

               最终模型就抽象成求最小生成树,用克鲁斯卡尔算法跑一下即可

    AC代码:

    #include<iostream>
    #include<vector>
    #include<set>
    #include<cstdio> 
    #include<algorithm>
    #define maxn 2005
    using namespace std;
    typedef long long ll;
    struct node{
    	int from,to;
    	ll cost;
    }e[maxn*maxn];//存储边的信息 
    int father[maxn];
    int cnt,N,city;
    vector<int> sta;//存建发电站的城市 
    vector<int> citya,cityb;//存储a b城市表示ab之间有电线 
    bool cmp(node a,node b){//比较函数 
    	return a.cost < b.cost ;
    }
    void init(){//初始化 
    	cnt = 0;
    	for(int i = 0;i<=N;i++){
    		father[i] = i;
    	}
    }
    int find(int x){//寻找根 
    	if(x == father[x]) return x;
    	return father[x] = find(father[x]);
    }
    bool same(int x,int y){//判断是否在一个集合 
    	return find(x)==find(y);
    }
    void unionSet(int x,int y){ //并查集合并 
    	int u = find(x),v = find(y);
    	if(u==v) return ;
    	father[u] = v;
    }
    long long kruskal(){ //求最小生成树 
    	ll res = 0;
    	std::sort(e,e+cnt,cmp);
    	for(int i = 0;i<cnt;i++){
    		if(same(e[i].from,e[i].to )) continue;
    		unionSet(e[i].from ,e[i].to );
    		if(e[i].from == 0 || e[i].to == 0){//判一下是否在城市建了发电站(利用源点判断) 
    			if(e[i].from == 0) sta.push_back(e[i].to ); 
    			else sta.push_back(e[i].from); 
    		}
    		else{//如果不是,存一些a,b两座连接的城市 
    			citya.push_back(e[i].from ),cityb.push_back(e[i].to);  
    		}
    		res+=e[i].cost ;
    	}
    	return res; 
    }
    void addedge(int u,int v,ll C){ //建边操作 
    	e[cnt].from = u,e[cnt].to = v,e[cnt].cost = C;
    	cnt++;
    }
    int main(){
    	cin>>N;
    	init(); 
    	vector<long long> vx,vy;
    	vector<long long> c,k;
    	for(int i = 0;i<N;i++){
    		int x,y;cin>>x>>y;
    		vx.push_back(x),vy.push_back(y);  
    	}
    	for(int i = 0;i<N;i++){
    		ll tc;cin>>tc;
    		c.push_back(tc); 
    	}
    	for(int i = 0;i<N;i++){
    		ll tk;cin>>tk;
    		k.push_back(tk); 
    	}
    	for(int i = 0;i<N;i++){//建立源点,和各个城市连接 
    		addedge(0,i+1,c[i]);
    	}
    	for(int i = 0;i<N;i++){//城市和城市之间建完全图 
    		for(int j = i+1;j<N;j++){
    			ll c = (abs(vx[i]-vx[j])+abs(vy[i]-vy[j]))*(k[i]+k[j]);
    			addedge(i+1,j+1,c);
    		}
    	}
    	ll ans = kruskal();
    	cout<<ans<<endl;
    	cout<<sta.size()<<endl;
    	for(int i = 0;i<sta.size();i++){
    		if(i==0) cout<<sta[i];
    		else cout<<" "<<sta[i];
    	}
    	cout<<endl;
    	cout<<citya.size()<<endl;
    	for(int i = 0;i<citya.size() ;i++){
    		cout<<citya[i]<<" "<<cityb[i]<<endl;
    	}
    	return 0;
    } 
  • 相关阅读:
    多媒体开发之图像---帧与场的区别
    Python之Python 安装环境搭建
    c/c++ c的第一个编译器
    多媒体开发之 H.264中NALU、RBSP、SODB的关系 (弄清码流结构)
    多媒体开发之h264中的sps---sps信息提取之帧率
    haproxy有关session的问题
    php的安装
    centos 6.5上部署jetty
    设置浏览器的颜色
    sed awk grep三剑客常用
  • 原文地址:https://www.cnblogs.com/AaronChang/p/12129623.html
Copyright © 2011-2022 走看看