zoukankan      html  css  js  c++  java
  • 【BZOJ3714】Kuglarz

    题目链接:https://www.lydsy.com/JudgeOnline/problem.php?id=3714


    qbxt大佬好多,我真的好弱。。。

    额额,这道题的话,关键在于划归到MST,剩下的基本都不是事了。

    如果我们把题目中的查询转换关系抽象成图,那么这应该是一张完全图。但如果我们想知道每个结点的奇偶性,找到一棵生成树即可。

    为什么呢,可以设想三个结点a,b,c,如果我们通过查询[a,b]和[b+1,c]得到了[a,c]的奇偶性,就不会再通过查询[a,c]的奇偶性得到了。

    而每条边(查询)是有费用的,把费用看成边权,MST可以做到费用最小。

    但这个题在建图时注意,由于查询[i,i]也是有费用的,所以不要把i点建成一个点。

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 const int maxn=2005,maxm=3e6+5;
     5 int n,eid;
     6 long long ans;
     7 struct Edge {
     8     int u,v,w;
     9     Edge(int u=0,int v=0,int w=-1):u(u),v(v),w(w) {}
    10     bool operator < (const Edge& rhs) const {
    11         return w<rhs.w;
    12     }
    13 } edge[maxm];
    14 int f[maxn];
    15 int dj_find(int i) {
    16     if(i==f[i]) return i;
    17     return f[i]=dj_find(f[i]);
    18 }
    19 void dj_merge(int a,int b) {
    20     a=dj_find(a);b=dj_find(b);
    21     if(dj_find(a)!=dj_find(b)) f[a]=b;
    22 }
    23 int main() {
    24     scanf("%d",&n);
    25     int c;
    26     for(int i=1;i<=n;++i)
    27         for(int j=i;j<=n;++j) {
    28             scanf("%d",&c);
    29             edge[++eid]=Edge(i-1,j,c);
    30         }
    31     for(int i=0;i<=n;++i) f[i]=i;
    32     sort(edge+1,edge+eid+1);
    33     for(int i=1;i<=eid;++i) {
    34         int u=edge[i].u,v=edge[i].v;
    35         if(dj_find(u)!=dj_find(v)) {
    36             ans+=edge[i].w;
    37             dj_merge(u,v);
    38         }
    39     }
    40     printf("%lld",ans);
    41     return 0;
    42 }
    AC代码(Kruskal)

    时隔一月,重新又做。。。

    重新写一下对于为什么是求MST的理解:问题其实是确定每个杯子的奇偶性,如果知道了每个前缀的奇偶性就可以了,因为0的奇偶性是确定的,实际上知道每个杯子的奇偶性也就知道了,因此二者是等价的。[0,a],[a,b]和[0,b],如果知道了其中二者,就可以知道第三个,而题目要求花费最小,想象一下,这不就是一棵有n+1个点的树,你希望从0到其他各个结点都连通,且边的费用和最小吗?

    上次用的Kruskal,明明是张完全图。。。这次好好写一下堆优化的Prim。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <algorithm>
     4 #include <queue>
     5 
     6 using namespace std;
     7 
     8 inline int get_num() {
     9     int num = 0;
    10     char c = getchar();
    11     while (c < '0' || c > '9') c = getchar();
    12     while (c >= '0' && c <= '9')
    13         num = num * 10 + c - '0', c = getchar();
    14     return num;
    15 }
    16 
    17 const int maxn = 2005, inf = 0x3f3f3f3f;
    18 
    19 int n, cost[maxn][maxn];
    20 long long ans;
    21 
    22 int dist[maxn], vis[maxn];
    23 
    24 struct node {
    25     int id, dist;
    26     node(int i, int d) : id(i), dist(d) {}
    27     bool operator < (const node& rhs) const {
    28         return dist > rhs.dist;
    29     }
    30 };
    31 
    32 priority_queue<node> q;
    33 
    34 inline void prim() {
    35     memset(dist, inf, sizeof(dist));
    36     dist[0] = 0;
    37     q.push(node(0, 0));
    38     while (!q.empty()) {
    39         int u = q.top().id;
    40         q.pop();
    41         if (vis[u]) continue;
    42         vis[u] = 1;
    43         ans += dist[u];
    44         for (int v = 1; v <= n; ++v)
    45             if (!vis[v] && cost[u][v] < dist[v]) {
    46                 dist[v] = cost[u][v];
    47                 q.push(node(v, dist[v]));
    48             }
    49     }
    50 }
    51 
    52 int main() {
    53     n = get_num();
    54     for (int i = 1; i <= n; ++i)
    55         for (int j = i; j <= n; ++j)
    56             cost[i - 1][j] = cost[j][i - 1] = get_num();
    57     prim();
    58     printf("%lld", ans);
    59     return 0;
    60 }
    AC代码(Prim)
  • 相关阅读:
    Spark小课堂Week3 FirstSparkApp(RDD开发)
    Catalyst揭秘 Day5 optimizer解析
    Spark小课堂Week2 Hello Streaming
    Spark小课堂Week1 Hello Spark
    Catalyst揭秘 Day4 analyzer解析
    Catalyst揭秘 Day3 sqlParser解析
    Catalyst揭秘 Day2 Catalyst源码初探
    Catalyst揭秘 Day1 Catalyst本地解析
    java泛型
    java中数组以及集合
  • 原文地址:https://www.cnblogs.com/Mr94Kevin/p/9735608.html
Copyright © 2011-2022 走看看