zoukankan      html  css  js  c++  java
  • CodeForces

    题目链接

    题目大意

      给你n个点,你可以在这个点上建站,也可以通过一条边将这个点与站点(直接/间接)连通。

    解题思路

      本题主要是考察建图技巧,因为每个点要么建站,要么与其他点连通,并且至少有一个站点,所以我们再加入一个点,这个点与所有点连通,并且花费是每个点建站的花费,然后再把所有点建一个完全图跑最小生成树就解决问题了。

    代码

    const int maxn = 2e3+10;
    const int maxm = 1e7+10;
    int n;
    struct INFO {
    	int x, y;
    } info[maxn];
    int c[maxn], k[maxn], tot, p[maxn];
    ll g[maxn][maxn], d[maxn];
    bool vis[maxn];
    ll prim() {
    	clr(d, 0x3f);
    	d[n+1] = 0;
    	int pre;
    	for (int i = 1; i<=n; ++i) {
    		int u = 0;
    		for (int j = 1; j<=n+1; ++j)
    			if (!vis[j] && (u==0 || d[j]<d[u])) u = j;
    		vis[u] = 1; 
    		for (int v = 1; v<=n+1; ++v)
    			if (!vis[v] && d[v]>g[u][v]) {
    				p[v] = u;
    				d[v] = g[u][v];
    			} 
    	}
    	ll sum = 0;
    	for (int i = 1; i<=n+1; ++i) sum += d[i];
    	return sum;
    }
    int main(){
    	cin >> n;
    	for (int i = 1; i<=n; ++i) cin >> info[i].x >> info[i].y;
    	for (int i = 1; i<=n; ++i) cin >> c[i];
    	for (int i = 1; i<=n; ++i) cin >> k[i];
    	for (int i = 1; i<=n; ++i) g[i][n+1] = g[n+1][i] = c[i];
    	for (int i = 1; i<=n; ++i)
    		for (int j = i+1; j<=n; ++j) {
    			ll d = 1LL*(abs(info[i].x-info[j].x)+abs(info[i].y-info[j].y))*(k[i]+k[j]);
    			g[i][j] = g[j][i] = d;
    		}
    	cout << prim() << endl;
    	vector<int> ans1;
    	vector<P> ans2;
    	for (int i = 1; i<=n; ++i) {
    		if (p[i]==n+1) ans1.push_back(i);
    		else ans2.push_back({p[i], i});
    	}
    	int sz = ans1.size();
    	cout << sz << endl;
    	for (int i = 0; i<sz; ++i) printf(i==sz-1 ? "%d
    ":"%d ", ans1[i]);
    	sz = ans2.size();
    	cout << sz << endl;
    	for (int i = 0; i<sz; ++i) printf("%d %d
    ", ans2[i].x, ans2[i].y);
    	return 0;	
    }
    
  • 相关阅读:
    经典入门_排序
    经典入门_贪心算法
    经典入门_Hash的应用
    经典入门_排序
    uva 839
    uva 327
    uva 699
    uva 712
    uva 297
    uva 548
  • 原文地址:https://www.cnblogs.com/shuitiangong/p/14399530.html
Copyright © 2011-2022 走看看