首页 > 代码库 > 洛谷2266 爱的距离

洛谷2266 爱的距离

 

题目描述 Description
但好日子却不长久。Soha的手下大将恶魔猎手在此时背叛了他,自立为王,率领深藏在世界之轴的龙族叛变,并掳走了公主Ami。Soha在与恶魔猎手的战斗中,遭遇围杀,被困在一个荒芜人烟的大岛上。但在经过勘探后,他惊喜地发现,Ami也同时被恶魔猎手关押在这座岛上!
经过精心研究,Soha发现关押Ami的地牢需要若干把钥匙才能打开,而钥匙则被埋藏在一系列的法阵中。凭借着自己的身手与魔力,Soha是能够破解法阵、获得钥匙的。法阵是一个M*N大小的矩阵,法阵中的每一格都具有自己的高度。其中,有一部分格中埋藏着钥匙,但Soha法力不足,无法直接挖取。而他发现,只需从埋藏着钥匙的格子出发向四周的格子走,并在不少于T个的独立法阵格子中施法(包括埋藏钥匙的格子本身也要施法),便可挖出钥匙。换句话说,在他每次挖掘钥匙之前,都必须先从埋藏钥匙的格子开始,走过周围的T-1个不重复的格子。
虽然Soha施法不需要耗费体力,但他在移动的过程中,需要耗费一定量的体力(体育不及格233)。从一个格子移动到另一个格子中所耗费的体力值为两个格子的高度值之差的绝对值。
对于每个埋藏钥匙的格子来说,定义其难度值P为在施法过程中,每次在各个格子间移动的所需耗费的体力的最大值。
而Soha则希望让这个难度值越小越好。因为,只有保留足够多的体力,他才能营救Ami,并两人合力打败恶魔猎手的背叛。
所以,他想知道所有埋藏钥匙的点的难度值的和最小值可以是多少?

思路: 题目比较繁琐,但思路简单。将每相邻的两个格连一条边,然后就是最小生成树了,用并查集维护(先把边排升序,保存每个集合中的元素个数和1的个数)。每次合并的时候,判断合并后元素总和是否大于t,对于合并前的两个集合,将原集合没有合并时的元素中和与t比较,若元素总数<t,则ans+=原集合中1的个数*边长。最后输出ans。
一开始数组和变量都开小了,很惨的。。。wa了好久,终于AC了。。。

code:
#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
struct use{
int st,en;
long long va;
}a[1000000];
int map[1001][1001],sum[800000]={0},sum1[800000]={0},fa[800001]={0};
int my_comp(const use &x,const use &y)
{
if (x.va<y.va) return 1;
return 0;
}
int rool(int x)
{
if (fa[x]!=x) fa[x]=rool(fa[x]);
return fa[x];
}
int main()
{
    int n,m,t,i,j,p,tot=0,r1,r2;
    long long ans=0,x;
scanf("%d%d%d",&n,&m,&t);
for (i=1;i<=n;++i)
  for (j=1;j<=m;++j)
  {
   p=(i-1)*m+j;
   scanf("%lld",&x);
   map[i][j]=x;
   if (j>1) 
   {
   ++tot;
   a[tot].st=p-1;
   a[tot].en=p;
   a[tot].va=abs(map[i][j]-map[i][j-1]);
   }
   if (i>1)
   {
   ++tot;
   a[tot].st=p-m;
   a[tot].en=p;
   a[tot].va=abs(map[i-1][j]-map[i][j]);
   }
  }
sort(a+1,a+tot+1,my_comp);
for (i=1;i<=n;++i)
  for (j=1;j<=m;++j)
  {
    scanf("%lld",&x);
    p=(i-1)*m+j;
    sum1[p]=x;
  }
for (i=1;i<=n*m;++i)
{
      sum[i]=1;
  fa[i]=i;
    }
for (i=1;i<=tot;++i)
{
r1=rool(a[i].st);
r2=rool(a[i].en);
if (r1!=r2)
{
if (sum[r2]+sum[r1]>=t)
{
if (sum[r1]<t)
{
ans=ans+sum1[r1]*a[i].va;
}
if (sum[r2]<t)
{
        ans=ans+sum1[r2]*a[i].va;
    }
}
sum[r2]=sum[r2]+sum[r1];
sum1[r2]=sum1[r2]+sum1[r1];
fa[r1]=r2;
}
}
printf("%lld\n",ans);

洛谷2266 爱的距离