BZOJ4886: [Lydsy2017年5月月赛]叠塔游戏

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

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


/*
严格递增的条件是没用的,等价于给每个矩形确定一个独一无二的底边长,最大化高的和
对于每个矩形(a,b),在a-b之间建一条边,若方向是a->b则代表底边是a,高是b,
那么一组可行解中每个点最多只有一条出边
考虑每个连通块,首先每个点会贡献(deg[i]-1)*val[i],其次若这个连通块是棵树,
那么选取val最大的点作为根可以额外得到val的收益
时间复杂度O(nlogn)
*/

#include<cstdio>
#include<algorithm>
#include<map>
using namespace std;
const int N=500010,inf=~0U>>1;
int n,m,i,x,y;
int val[N],d[N],g[N],v[N],nxt[N],ed,ma,sum;bool vis[N];
long long ans;
map<int,int>idx;
inline void add(int x,int y){d[x]++;v[++ed]=y;nxt[ed]=g[x];g[x]=ed;}
void dfs(int x){
  if(vis[x])return;
  vis[x]=1;
  ma=max(ma,val[x]);
  ans+=1LL*val[x]*(d[x]-1);
  sum+=d[x]-2;
  for(int i=g[x];i;i=nxt[i])dfs(v[i]);
}
int main(){
  scanf("%d",&n);
  for(i=1;i<=n;i++){
    scanf("%d%d",&x,&y);
    if(!idx[x]){
      idx[x]=++m;
      val[m]=x;
    }
    if(!idx[y]){
      idx[y]=++m;
      val[m]=y;
    }
    x=idx[x];
    y=idx[y];
    add(x,y);
    add(y,x);
  }
  for(i=1;i<=m;i++)if(!vis[i]){
    ma=sum=0;
    dfs(i);
    if(sum<0)ans+=ma;
  }
  printf("%lld",ans);
}


  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值