前面用贪心算法解决的方案也可以AC,但是对于每一个数据,都要从它的deadline开始寻找,最坏的情况是O(n^2)。所以这里用并查集来优化查找的步骤。
怎么优化,其实这个思想在NYOJ207食物链那道题里面就有体现。并查集有两个功能,查找根节点和合并根节点,如果每一条路径都比较短的话,查找的效率就会很高。怎么样使每条路径都比较短呢?那就是尽可能的将所有节点直接连接到根节点,也就是呈现一个星形。比如要加入一个节点,就必须逐步的更新根节点到该节点父节点以前的所有节点的父节点,使它们都直接与根节点相连。这种条件下,内存要多一点(N*3字节),但时间会快很多(至少200ms)。
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
const int N = 10005;
int arr[N][2];
int parent[N];
int compare(const void *a, const void *b)
{
int *p1 = (int *)a;
int *p2 = (int *)b;
return p2[0] - p1[0];
}
int Find(int x)
{
if(parent[x] == -1)
return x;
parent[x] = Find(parent[x]);
return parent[x];
}
int main()
{
int n,i;
int r,sum;
while(scanf("%d", &n) != EOF)
{
memset(parent, -1, sizeof(parent));
for(i = 0; i < n; ++i)
scanf("%d %d", &arr[i][0], &arr[i][1]);
qsort(arr, n, 2*sizeof(int), compare);
sum = 0;
for(i = 0; i < n; ++i)
{
r = Find(arr[i][1]);
if(r > 0)//如果有日期可用
{
sum += arr[i][0];
parent[r] = Find(r - 1);
}
}
printf("%d\n", sum);
}
}