题目大意:在滑雪场中,每一个景点有一个高度。现在小明在一号节点。i和j之间有单向边当且仅当i的高度不高于j。问小明最多可以去多少个景点,和最小总费用。
思路:这是一道数学证明的好题。
第一问比较水,直接将可行的边连接起来,然后BFS出解。
第二问就比较难搞了。不难看出,直接用朱刘算法是不可行的,因为朱刘算法的时间复杂度达到了O(mn),而这个题至少需要一个O(mlogm)的算法。
恩?你说mlogm?难道是最小生成树?但是这图中都是单向边啊。
经过了上网找题解,和同学研究之后,终于弄明白了这题的精髓。简要说明一下做法和正确性。
做法很简单。只需要改变一下边的排序,第一键值为终点的高度,第二键值为边的权值。然后正常跑MST就行了。可这是为什么?
首先明确,在一个高度中,两点之间有边就一定是双向边。那么在一个高度且有边的点会形成一个强连通分量。将所有能够从1遍历到的点进行缩点之后,图会变成以1所在的SCC为起点的可拓扑图(因为高度比1还高的点一定无法到达,所以没有边)。
之后从上向下考虑,每一个SCC的高度一定是一样的。而终点为这个高度的边有两种,一种是从更高处的SCC连到这个高度的SCC的单向边,和这个SCC中的双向边,在处理这一层的时候,可以吧这两种边都看成是无向边,也就可以套用正常的MST了。
CODE:
#include <queue>
#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#define MAX 2000010
using namespace std;
int h[MAX];
struct Edge{
int x,y,length;
bool operator <(const Edge &a) const {
if(h[y] == h[a.y]) return length < a.length;
return h[y] > h[a.y];
}
void Read() {
scanf("%d%d%d",&x,&y,&length);
if(h[x] < h[y]) swap(x,y);
}
}edge[MAX];
int points,edges;
int head[MAX],total;
int next[MAX],aim[MAX];
int father[MAX];
bool v[MAX];
inline void Add(int x,int y)
{
next[++total] = head[x];
aim[total] = y;
head[x] = total;
}
int BFS()
{
static queue<int> q;
int re = 1;
v[1] = true;
q.push(1);
while(!q.empty()) {
int x = q.front(); q.pop();
for(int i = head[x]; i; i = next[i])
if(!v[aim[i]]) {
v[aim[i]] = true;
++re;
q.push(aim[i]);
}
}
return re;
}
int Find(int x)
{
if(father[x] == x) return x;
return father[x] = Find(father[x]);
}
long long MST()
{
long long re = 0;
sort(edge + 1,edge + edges + 1);
for(int i = 1; i <= points; ++i) father[i] = i;
for(int i = 1; i <= edges; ++i) {
if(!v[edge[i].x] || !v[edge[i].y]) continue;
int fx = Find(edge[i].x);
int fy = Find(edge[i].y);
if(fx != fy) {
father[fx] = fy;
re += edge[i].length;
}
}
return re;
}
int main()
{
cin >> points >> edges;
for(int i = 1; i <= points; ++i)
scanf("%d",&h[i]);
for(int i = 1; i <= edges; ++i) {
edge[i].Read();
Add(edge[i].x,edge[i].y);
if(h[edge[i].x] == h[edge[i].y])
Add(edge[i].y,edge[i].x);
}
cout << BFS() << ' ';
cout << MST() << endl;
return 0;
}BZOJ 2753 SCOI 2012 滑雪与时间胶囊 最小生成树
原文地址:http://blog.csdn.net/jiangyuze831/article/details/41750715