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

来源:互联网 发布:淘宝助理导出宝贝 编辑:程序博客网 时间:2024/06/05 03:09

题目链接: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
原创粉丝点击