zoukankan      html  css  js  c++  java
  • 【BZOJ】3714: [PA2014]Kuglarz

    题意

    (n(1 le n le 2000))个数每个数是(0)(1),现在可以花费(c_{i, j})知道([i, j])的奇偶性,问将所有数都找出来的最小花费。

    分析

    如果知道了所有的前缀和,那么我们就知道了所有数。
    对于区间([i, j]),那么如果知道了(sum[i-1]),那么就知道了(sum[j]),连边。反之亦然。
    最终其实我们就是将前缀和(0)(n)都放到一个集合里,由于知道了前缀和(0)=0,所以就知道了所有数。

    题解

    所以问题转化为找出一种方案使得所有前缀和在同一集合内的最小解。
    最小生成树= =。

    #include <bits/stdc++.h>
    using namespace std;
    typedef long long ll;
    const int N=2005;
    int n, s[N], p[N], tot;
    struct E {
    	int x, y, w;
    }e[N*N/2];
    inline bool cmp(const E &a, const E &b) {
    	return a.w<b.w;
    }
    inline int find(const int x) {
    	return x==p[x]?x:p[x]=find(p[x]);
    }
    inline int getint() {
    	int x=0;
    	char c=getchar();
    	for(; c<'0'||c>'9'; c=getchar());
    	for(; c>='0'&&c<='9'; c=getchar()) {
    		x=x*10+c-'0';
    	}
    	return x;
    }
    int main() {
    	scanf("%d", &n);
    	for(int i=1; i<=n; ++i) {
    		for(int j=i; j<=n; ++j) {
    			e[tot++]=(E){i-1, j, getint()};
    		}
    		p[i]=i;
    	}
    	ll ans=0;
    	sort(e, e+tot, cmp);
    	for(int i=0; i<tot; ++i) {
    		int fx=find(e[i].x), fy=find(e[i].y);
    		if(fx!=fy) {
    			if(s[fx]>s[fy]) {
    				swap(fx, fy);
    			}
    			ans+=e[i].w;
    			p[fx]=fy;
    			s[fy]+=s[fx]==s[fy]?1:0;
    		}
    	}
    	printf("%lld
    ", ans);
    	return 0;
    }
  • 相关阅读:
    js获取当前日期
    Mysql错误1452
    数字输入框禁止输入字母
    laravel关联外键报错
    golang for range channel
    golang实现简单哈希表(拉链法解决冲突)
    K个一组反转链表(golang)
    golang 少见的语法问题(无用)
    golang实现循环队列
    数组中连续序列和最大值(循环数组)
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4986032.html
Copyright © 2011-2022 走看看