题目:http://61.187.179.132/JudgeOnline/problem.php?id=2753
Description
a180285非常喜欢滑雪。他来到一座雪山,这里分布着M条供滑行的轨道和N个轨道之间的交点(同时也是景点),而且每个景点都有一编号i(1<=i<=N)和一高度Hi。a180285能从景点i 滑到景点j 当且仅当存在一条i 和j 之间的边,且i 的高度不小于j。 与其他滑雪爱好者不同,a180285喜欢用最短的滑行路径去访问尽量多的景点。如果仅仅访问一条路径上的景点,他会觉得数量太少。于是a180285拿出了他随身携带的时间胶囊。这是一种很神奇的药物,吃下之后可以立即回到上个经过的景点(不用移动也不被认为是a180285 滑行的距离)。请注意,这种神奇的药物是可以连续食用的,即能够回到较长时间之前到过的景点(比如上上个经过的景点和上上上个经过的景点)。 现在,a180285站在1号景点望着山下的目标,心潮澎湃。他十分想知道在不考虑时间
胶囊消耗的情况下,以最短滑行距离滑到尽量多的景点的方案(即满足经过景点数最大的前提下使得滑行总距离最小)。你能帮他求出最短距离和景点数吗?
Input
输入的第一行是两个整数N,M。
接下来1行有N个整数Hi,分别表示每个景点的高度。
接下来M行,表示各个景点之间轨道分布的情况。每行3个整数,Ui,Vi,Ki。表示
编号为Ui的景点和编号为Vi的景点之间有一条长度为Ki的轨道。
Output
输出一行,表示a180285最多能到达多少个景点,以及此时最短的滑行距离总和。
Sample Input
3 3
3 2 1
1 2 1
2 3 1
1 3 10
Sample Output
3 2
HINT
【数据范围】
对于30%的数据,保证 1<=N<=2000
对于100%的数据,保证 1<=N<=100000
对于所有的数据,保证 1<=M<=1000000,1<=Hi<=1000000000,1<=Ki<=1000000000。
题解:
题目的意思就是首先找到从编号为一的点开始走,能走的一定是高度不高于它的点,然后得到一个点集,把边加进去后得到一张新图,求这个图的最小树形图即可了。
题意如此简单………………利用了该题的某些神奇性质………………把边按终点的高度为第一关键字,边长为第二关键字,排个序后就可以做了…………………………注意答案要64为整数即可…………………………
View Code
1 #include<cstdio>
2 #include<cstdlib>
3 #include<cstring>
4 #include<algorithm>
5 #include<queue>
6
7 using namespace std;
8
9 const int maxn=100001;
10 const int maxm=2000001;
11
12 int sum,en,h[maxn],f[maxn],n,m;
13
14 long long ans;
15
16 bool use[maxn];
17
18 queue<int> que;
19
20 struct edge
21 {
22 int s,e,d;
23 edge *next;
24 }*v[maxn],ed[maxm];
25
26 void add_edge(int s,int e,int d)
27 {
28 en++;
29 ed[en].next=v[s];v[s]=ed+en;v[s]->s=s;v[s]->e=e;v[s]->d=d;
30 }
31
32 void bfs()
33 {
34 use[1]=true;
35 sum=1;
36 que.push(1);
37 f[1]=1;
38 while (que.size())
39 {
40 int now=que.front();
41 que.pop();
42 for (edge *e=v[now];e;e=e->next)
43 if (!use[e->e])
44 {
45 f[e->e]=e->e;
46 use[e->e]=true;
47 sum++;
48 que.push(e->e);
49 }
50 }
51 }
52
53 bool cmp(edge a,edge b)
54 {
55 return h[a.e]>h[b.e] || (h[a.e]==h[b.e] && a.d<b.d);
56 }
57
58 int getf(int now)
59 {
60 return (f[now]==now)?now:f[now]=getf(f[now]);
61 }
62
63 int main()
64 {
65 freopen("ski.in","r",stdin);
66 freopen("ski.out","w",stdout);
67
68 scanf("%d%d",&n,&m);
69 for (int a=1;a<=n;a++)
70 scanf("%d",&h[a]);
71 for (int a=1;a<=m;a++)
72 {
73 int x,y,d;
74 scanf("%d%d%d",&x,&y,&d);
75 if (h[x]>=h[y]) add_edge(x,y,d);
76 if (h[y]>=h[x]) add_edge(y,x,d);
77 }
78 bfs();
79 sort(ed+1,ed+en+1,cmp);
80 for (int a=1;a<=n;a++)
81 f[a]=a;
82 for (int a=1;a<=en;a++)
83 {
84 if (!use[ed[a].s] || !use[ed[a].e]) continue;
85 int s=ed[a].s,e=ed[a].e;
86 int fx=getf(s),fy=getf(e);
87 if (fx!=fy)
88 {
89 ans=ans+ed[a].d;
90 f[fx]=fy;
91 }
92 }
93 printf("%d %lld\n",sum,ans);
94
95 return 0;
96 }