zoukankan      html  css  js  c++  java
  • Codeforces 1245D Shichikuji and Power Grid

    思路:

    这题一共有两种思路:
    1.设立一个虚点,将所有点和它连接,costci,然后其它点两两相连,cost为两点之间建立连接所需价格,然后求这个图的最小生成树,求出来的树中,和虚点相连的点就是自己设发电站的点,两个顶点都不是虚点的边就是需要修路的边;(在求解过程中需要使用long long
    2.由贪心思想可以得知,所有ci中最小的那个i点一定要设立发电站,此时我们遍历所有j>=1&&j<=n&&j!=i,这时j有两种选择:(1)和i相连 (2)自己建发电站;我们在这两种里面选择花费最小的那一种并更新cj,并记录更小的情况是自己建站还是和i连接(只是更新cj,还未决定到底是自己建or连接ior连接其它点),全部更新一遍之后,我们再在所有未建发电站的点里选取c最小的那一个,对它通电(是自己建站还是进行连接,就根据之前的记录),然后依次循环到所有点通电就ok了~(因为笔者只实现了最小生成树,这种贪心方法没有贴出代码,所以我就稍微啰嗦一点了QAQ)

    代码:

    #define IOS ios::sync_with_stdio(false);cin.tie(0)
    #include<bits/stdc++.h>
    using namespace std;
    typedef pair<int,int> P;
    typedef long long LL;
    #define fi first
    #define sc second
    #define pb(a) push_back(a)
    #define mp(a,b) make_pair(a,b)
    #define rp(i,n) for(int i=0;i<n;i++)
    #define rpn(i,n) for(int i=1;i<=n;i++)
    const int MAX_N=2000+99; 
    int par[MAX_N],rank_u[MAX_N];  //MAX_N集合里最多元素个数
    void init_union(int n){
    	for(int i=0;i<n;i++){
    		par[i]=i;
    		rank_u[i]=0;
    	}
    }
    int find(int x){
    	if(par[x]==x) return x;
    	else return par[x]=find(par[x]);
    }
    void unite(int x,int y){
    	x=find(x);
    	y=find(y);
    	if(x==y) return;
    	if(rank_u[x]<rank_u[y]) par[x]=y;
    	else{
    		par[y]=x;
    		if(rank_u[x]==rank_u[y]) rank_u[x]++;
    	}
    }
    bool same(int x,int y){
    	return find(x)==find(y);
    }
    struct edge{int u,v;LL cost;};
    bool cmp(const edge& e1,const edge& e2){
    	return e1.cost<e2.cost;
    }
    const int MAX_E=2001000+99;
    edge es[MAX_E];
    int V,E;//顶点数和边数
    vector<int> v1;//自己建发电站
    vector<P> v2;//连接别的发电站 
    LL kruskal(){
    	sort(es,es+E,cmp);
    	init_union(V);
    	LL res=0;
    	for(int i=0;i<E;i++){
    		edge e=es[i];
    		if(!same(e.u,e.v)){
    			if(e.u&&e.v) v2.pb(mp(e.u,e.v));
    			else v1.pb(e.u?e.u:e.v);
    			unite(e.u,e.v);
    			res+=e.cost;
    		}
    	}
    	return res;
    }
    P cod[MAX_N];
    LL K[MAX_N];
    LL cost(int a,int b){return (K[a]+K[b])*(abs(cod[a].fi-cod[b].fi)+abs(cod[a].sc-cod[b].sc));}
    int main(){
    	IOS;
    	int n;
    	cin>>n;
    	V=n+1; E=(n+1)*n/2;
    	rpn(i,n) cin>>cod[i].fi>>cod[i].sc;
    	int pos=0;
    	rpn(i,n){
    		LL cost;
    		cin>>cost;
    		es[pos++]=edge{0,i,cost};
    	}
    	rpn(i,n) cin>>K[i];
    	for(int i=1;i<n;i++){
    		for(int j=i+1;j<=n;j++) es[pos++]=edge{i,j,cost(i,j)};
    	}
    	cout<<kruskal()<<'
    ';
    	cout<<v1.size()<<'
    '<<v1[0];
    	for(int i=1;i<v1.size();i++) cout<<' '<<v1[i];
    	cout<<'
    '<<v2.size()<<'
    ';
    	rp(i,v2.size()) cout<<v2[i].fi<<' '<<v2[i].sc<<'
    ';
    	return 0;
    }
    
  • 相关阅读:
    括号匹配(有点复杂,因为它讲得详细)
    A+B/A*B求A和B
    构造哈夫曼树
    用栈实现进制转换
    实现二叉树各种基本运算的算法
    十六进制加法
    求二叉树中叶子结点到根结点的路径
    SilverLight4常见问题及解决办法
    Silverlight中自定义控件
    Silverlight发布时的优化工作
  • 原文地址:https://www.cnblogs.com/yuhan-blog/p/12308846.html
Copyright © 2011-2022 走看看