SCOI 2010 滑雪

题目描述

a180285非常喜欢滑雪。他来到一座雪山,这里分布着 MM 条供滑行的轨道和 NN 个轨道之间的交点(同时也是景点),而且每个景点都有一编号 ii ( 1 le i le N1iN )和一高度 H_iHi 。a180285能从景点 ii 滑到景点 jj 当且仅当存在一条 ii 和 jj 之间的边,且 ii 的高度不小于 jj 。 与其他滑雪爱好者不同,a180285喜欢用最短的滑行路径去访问尽量多的景点。如果仅仅访问一条路径上的景点,他会觉得数量太少。于是a180285拿出了他随身携带的时间胶囊。这是一种很神奇的药物,吃下之后可以立即回到上个经过的景点(不用移动也不被认为是a180285 滑行的距离)。请注意,这种神奇的药物是可以连续食用的,即能够回到较长时间之前到过的景点(比如上上个经过的景点和上上上个经过的景点)。 现在,a180285站在 11 号景点望着山下的目标,心潮澎湃。他十分想知道在不考虑时间胶囊消耗的情况下,以最短滑行距离滑到尽量多的景点的方案(即满足经过景点数最大的前提下使得滑行总距离最小)。你能帮他求出最短距离和景点数吗?

输入输出格式

输入格式:

输入的第一行是两个整数 N,MN,M 。

接下来 11 行有 NN 个整数 H_iHi ,分别表示每个景点的高度。

接下来 MM 行,表示各个景点之间轨道分布的情况。每行 33 个整数, U_i,V_i,K_iUi,Vi,Ki 。表示编号为 U_iUi 的景点和编号为 V_iVi 的景点之间有一条长度为 K_iKi 的轨道。

输出格式:

输出一行,表示a180285最多能到达多少个景点,以及此时最短的滑行距离总和。

输入输出样例

输入样例#1:
3 3 
3 2 1 
1 2 1 
2 3 1 
1 3 10 
输出样例#1:
3 2

说明

【数据范围】

对于 30\%30% 的数据,保证 1 le N le 20001N2000

对于 100\%100% 的数据,保证 1 le N le 10^51N105

对于所有的数据,保证 1 le M le 10^61M106 , 1 le H_i le 10^91Hi109 , 1 le K_i le 10^91Ki109 。

-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

(题外话:今天真是亢奋了一天ovo)

首先bfs一遍,筛出从1号点可以到达的点,并且用这些点建立一个新图

然后用最小生成时树跑一遍新图,记录路径长度....然后就没有然后了?

这是代码

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<cmath>
 5 #include<algorithm>
 6 #include<queue>
 7 #define N 1000010
 8 #define LL long long
 9 using namespace std;
10 int n,m;
11 LL sum,ans,fa[N],h[N];
12 struct rockdu
13 {
14     LL u,v,w,nxt;
15 }e[N*2],d[N*2];
16 int first[N],cnt,cnnt,head[N];
17 bool vis[N];
18 bool cmp(rockdu x,rockdu y)
19 {//终点的高度为第一关键字从大到小排序,边长为第二关键字从小到大排序 
20     if(h[x.v]!=h[y.v]) return h[x.v]>h[y.v];
21     return x.w<y.w;
22 }
23 void ade(LL u,LL v,LL w)
24 {
25     e[++cnt].nxt=first[u];first[u]=cnt;
26     e[cnt].u=u;e[cnt].v=v;e[cnt].w=w;
27 }
28 void adenew(LL u,LL v,LL w)
29 {
30     d[++cnnt].nxt=head[u];head[u]=cnnt;
31     d[cnnt].u=u;d[cnnt].v=v;d[cnnt].w=w;
32 }
33 void bfs()//buildnew
34 {
35     queue<LL>q;
36     q.push(1);vis[1]=1;
37     while(!q.empty())
38     {
39         LL u=q.front(); q.pop();
40         for(register LL i=first[u];i;i=e[i].nxt)
41         {
42             LL v=e[i].v;
43             adenew(u,v,e[i].w);
44             if(!vis[v])
45             {
46                 vis[v]=1;
47                 sum++;
48                 q.push(v);
49             }
50         }
51     }
52 }
53 //kruskal
54 inline long long la(long long x)
55 {
56     if(fa[x]!=x) fa[x]=la(fa[x]);
57     return fa[x];
58 }
59 inline char nc(){
60     static char buf[100000],*p1=buf,*p2=buf;
61     return p1==p2&&(p2=(p1=buf)+fread(buf,1,100000,stdin),p1==p2)?EOF:*p1++;
62 }
63 inline long long read(){
64     char ch=nc();int sum=0;
65     while(!(ch>='0'&&ch<='9'))ch=nc();
66     while(ch>='0'&&ch<='9')sum=sum*10+ch-48,ch=nc();
67     return sum;
68 }
69 int main()
70 {
71     n=read();m=read();
72     for(register LL i=1;i<=n;i++)
73     {
74         h[i]=read();
75         fa[i]=i;
76     }
77     for(register LL i=1;i<=m;i++)
78     {
79         LL a,b,c;
80         a=read();b=read();c=read();
81         if(h[a]>=h[b]) ade(a,b,c);
82         if(h[a]<=h[b]) ade(b,a,c);
83     }
84     bfs();
85     sort(d+1,d+cnnt+1,cmp);
86     for(register LL i=1;i<=cnnt;i++)
87     {
88         register LL x=la(d[i].u),y=la(d[i].v);
89         if(x!=y)
90         {
91             fa[x]=y;
92             ans+=d[i].w;
93         }
94     }
95     printf("%lld %lld",sum+1,ans);
96     return 0;
97 }
ovo

.

原文地址:https://www.cnblogs.com/kylara/p/9469617.html