3714: [PA2014]Kuglarz

3714: [PA2014]Kuglarz

链接

思路:

  好题。对于每个点都需要确定它的值,那么一个点可以直接询问[i,i]来确定,或者已经知道了[i,j]和[i+1,j]推出来。

  但是可能产生冲突,所以要增加一些限制。比如选了[1,1]和[2,2]就不能再选[1,2]了。

  还有一个结论:答案一定是询问n次。这个在纸上画一下吧。

  对于这些限制,刚好可以用生成树来做(树是不允许有环的),然后发现如果直接建图是不可以做的,需要将点化为边,在n+1个点中选n条边。

代码 

 1 #include<cstdio>
 2 #include<algorithm>
 3 #include<iostream>
 4 
 5 using namespace std;
 6 typedef long long LL;
 7 
 8 struct Edge{
 9     int u,v,w;
10     Edge() {} 
11     Edge(int a,int b,int c) {u=a,v=b,w=c;}
12     bool operator < (const Edge &x) const {
13         return w < x.w;
14     }
15 }e[5000100];
16 int fa[10010];
17 int tot = 0;
18 
19 inline int read() {
20     int x = 0,f = 1;char ch=getchar();
21     for (; ch<'0'||ch>'9'; ch=getchar()) if(ch=='-')f=-1;
22     for (; ch>='0'&&ch<='9'; ch=getchar()) x=x*10+ch-'0';
23     return x*f;
24 }
25 
26 int find(int x) {
27     return x==fa[x]?x:find(fa[x]);
28 }
29 int main () {
30     int n = read();
31     for (int i=1; i<=n; ++i) 
32         for (int j=i; j<=n; ++j) {
33             e[++tot] = Edge(i,j+1,read());
34         }
35     for (int i=1; i<=n+1; ++i) fa[i] = i;
36     sort(e+1,e+tot+1);
37     int cnt = 0;
38     LL ans = 0;    
39     for (int i=1; i<=tot; ++i) {
40         int u = e[i].u,v = e[i].v,w = e[i].w;
41         int fu = find(u),fv = find(v);
42         if (fu == fv) continue;
43         fa[fu] = fv;
44         ans += w;
45         cnt ++;
46         if (cnt == n) break;
47     }
48     cout << ans;
49     return 0;
50 }
原文地址:https://www.cnblogs.com/mjtcn/p/8716234.html