• BZOJ4886: [Lydsy1705月赛]叠塔游戏(环套树森林&贪心)


    4886: [Lydsy1705月赛]叠塔游戏

    Time Limit: 20 Sec  Memory Limit: 256 MB
    Submit: 198  Solved: 76
    [Submit][Status][Discuss]

    Description

    小Q正在玩一个叠塔的游戏,游戏的目标是叠出尽可能高的塔。在游戏中,一共有n张矩形卡片,其中第i张卡片的
    长度为a_i,宽度为b_i。小Q需要把所有卡片按一定顺序叠成一座塔,要求对于任意一个矩形,它的长度要严格大
    于它上边的任意一个矩形的长度。塔的高度为所有矩形的宽度之和。在游戏中,小Q可以将卡片翻转90度来使用,
    而且必须用上全部n张卡片。请写一个程序,帮助计算小Q能叠出最高的塔的高度。

    Input

    第一行包含一个正整数n(1<=n<=250000),即卡片的个数。
    接下来n行,每行两个正整数a_i,b_i(1<=a_i,b_i<=10^9),分别表示每张卡片的长度和宽度。

    Output

    输出一行一个整数,即最高的塔的高度,输入数据保证一定存在解。

    Sample Input

    3
    5 16
    10 5
    5 10

    Sample Output

    20

    HINT

    Source

    思路:要求长度递增,求最大宽度之和。 由于排序是自己定的,所以只要求长度不相同,求最大宽度之和。 这样的话,我们就尝试用最大费用流来建图,

    S向每个矩形连(1,0)(表示容量为1,费用为0)的边;     每个矩形向x连(1,y)的边,向y连(1,x)的边;     然后每个数向T连(1,0)的边。然后就是跑最大费用流。 由于数据太大,显然会超时。  这样的题一般可以贪心优化,可以对比bzoj4883,是一个套路。

    此题的定向和bzoj4883的定向不一样,此题的定向会决定答案的大小。  只有无环的连通块,根的贡献=度数,其他都是=度数-1。 所以此题不需要排序,只需要找连通块的最大值即可。

    #include<bits/stdc++.h>
    #define ll long long
    #define rep(i,a,b) for(int i=a;i<=b;i++)
    using namespace std;
    const int maxn=500010;
    int N,cnt,ma,sum,tot,a[maxn],b[maxn],fa[maxn],tag[maxn];
    int val[maxn],d[maxn],mx[maxn],Laxt[maxn],To[maxn],Next[maxn];
    map<int,int>idx; bool vis[maxn];ll ans;
    void add(int u,int v){ d[u]++;To[++cnt]=v;Next[cnt]=Laxt[u];Laxt[u]=cnt;}
    int find(int x){
        if(x==fa[x]) return x;
        return fa[x]=find(fa[x]);
    }
    int main(){
       int u,v; scanf("%d",&N);
       rep(i,1,N){
          scanf("%d%d",&u,&v);
          if(!idx[u]) idx[u]=++tot,val[tot]=u;
          if(!idx[v]) idx[v]=++tot,val[tot]=v;
          u=idx[u]; v=idx[v]; d[u]++; d[v]++;
          a[i]=u; b[i]=v;
       }
       rep(i,1,tot) fa[i]=i,mx[i]=val[i];
       rep(i,1,tot){
            int x=find(a[i]),y=find(b[i]);
            if(tag[x]&&tag[y]) continue;
            if(x==y) tag[x]=1;
            else fa[y]=x,tag[x]|=tag[y],mx[x]=max(mx[x],mx[y]);
       }
       rep(i,1,tot){
           ans+=(ll)(d[i]-1)*val[i];
           if(find(i)==i&&!tag[i]) ans+=mx[i];
       }
       printf("%lld",ans);
       return 0;
    }
    
  • 相关阅读:
    bzoj3527: [Zjoi2014]力 fft
    bzoj3295: [Cqoi2011]动态逆序对 cdq分治
    快速读入fread
    km板子(二分图最大权匹配)
    spfa毒瘤算法
    牛客网暑期ACM多校训练营(第三场)DEncrypted String Matching fft
    P4173 残缺的字符串 fft
    圆和多边形交模板
    hdu多校2C
    Codeforces Round #449 (Div. 1)C
  • 原文地址:https://www.cnblogs.com/hua-dong/p/9978110.html
Copyright © 2020-2023  润新知