[SCOI2012]滑雪与时间胶囊

题目描述

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

输入输出格式

输入格式:

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

接下来111行有NNN个整数HiH_iHi​​,分别表示每个景点的高度。

接下来MMM行,表示各个景点之间轨道分布的情况。每行333个整数,Ui,Vi,KiU_i,V_i,K_iUi​​,Vi​​,Ki​​。表示编号为UiU_iUi​​的景点和编号为ViV_iVi​​的景点之间有一条长度为KiK_iKi​​的轨道。

输出格式:

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

输入输出样例

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

说明

【数据范围】

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

对于100% 100\% 100%的数据,保证 1≤N≤105 1 \le N \le 10^5 1N105​​

对于所有的数据,保证 $ 1 \le M \le 10^6 , 1 \le H_i \le 10^9,1 \le K_i \le 10^9 $。

按照题目意思就是给你一个有向图,求一个最小树形图,然后如果你用朱刘算法来算,就只能得到70分

因为有神奇的胶囊,所以有向边又可以看成双向边

而且每个选中的景点可以从1用bfs求出数量cnt

可以保证一定有cnt那么多个

这道题的反向边只会在高度相同的点之间出现。如果把边先按终点高度排序为第一关键字,边长为第二关键字排序之后,就会保证优先到高点,同高点之间选小边,然后就不会出现反向的情况,所以可以用kruskal实现用O(mlog(m))的时间复杂度解决这道题。

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #include<queue>
 6 using namespace std;
 7 typedef long long lol;
 8 struct Edge
 9 {
10   int u,v;
11   lol w;
12 }e[2000001];
13 struct Node
14 {
15   int next,to;
16 }edge[2000001];
17 int set[100001],n,m,num,head[100001],cnt;
18 lol h[100001],ans;
19 bool vis[100001];
20 void add(int u,int v)
21 {
22   num++;
23   edge[num].next=head[u];
24   head[u]=num;
25   edge[num].to=v;
26 }
27 int find(int x)
28 {
29   if (set[x]!=x) set[x]=find(set[x]);
30   return set[x];
31 }
32 bool cmp(Edge a,Edge b)
33 {
34   if (h[a.v]!=h[b.v]) return h[a.v]>h[b.v];
35   return a.w<b.w;
36 }
37 void bfs()
38 {int i;
39   queue<int> Q;
40   Q.push(1);
41   vis[1]=1;
42   cnt=1;
43   while (Q.empty()==0)
44     {
45       int u=Q.front();
46       Q.pop();
47       for (i=head[u];i;i=edge[i].next)
48     {
49       int v=edge[i].to;
50       if (vis[v]==0)
51         {cnt++;
52           Q.push(v);
53           vis[v]=1;
54         }
55     }
56     }
57   cout<<cnt<<' ';
58 }
59 int main()
60 {int i,j;
61   cin>>n>>m;
62   for (i=1;i<=n;i++)
63     scanf("%lld",&h[i]);
64   for (i=1;i<=m;i++)
65     {
66       scanf("%d%d%lld",&e[i].u,&e[i].v,&e[i].w);
67       if (h[e[i].u]<h[e[i].v]) swap(e[i].u,e[i].v);
68       add(e[i].u,e[i].v);
69       if (h[e[i].u]==h[e[i].v]) add(e[i].v,e[i].u);
70     }
71   bfs();
72   sort(e+1,e+m+1,cmp);
73   for (i=1;i<=n;i++)
74     set[i]=i;
75   ans=0;j=0;
76   for (i=1;i<=m;i++)
77     {
78       if (vis[e[i].u]==0||vis[e[i].v]==0) continue;
79       int p=find(e[i].u);
80       int q=find(e[i].v);
81       if (p!=q)
82     {
83       set[p]=q;
84       ans+=e[i].w;
85       j++;
86       if (j==cnt-1) break;
87     }
88     }
89   cout<<ans;
90 }

 

转载于:https://www.cnblogs.com/Y-E-T-I/p/7470768.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
中描述了一个幼儿园里分配糖果的问题,每个小朋友都有自己的要求。问题的输入包括两个整数NN和KK,表示幼儿园里的小朋友数量和要满足的要求数量。接下来的KK行表示小朋友们的要求,每行有三个数字,XX,AA,BB。如果X=1,表示第AA个小朋友分到的糖果必须和第BB个小朋友分到的糖果一样多;如果X=2,表示第AA个小朋友分到的糖果必须少于第BB个小朋友分到的糖果;如果X=3,表示第AA个小朋友分到的糖果必须不少于第BB个小朋友分到的糖果;如果X=4,表示第AA个小朋友分到的糖果必须多于第BB个小朋友分到的糖果;如果X=5,表示第AA个小朋友分到的糖果必须不多于第BB个小朋友分到的糖果。这个问题可以被看作是一个差分约束系统的问题。 具体地说,可以使用差分约束系统来解决这个问题。差分约束系统是一种通过给变量之间的关系添加约束来求解最优解的方法。对于这个问题,我们需要根据小朋友们的要求建立约束条件,并通过解决这个约束系统来得出最小的糖果数量。 在问题的输入中,X的取值范围为1到5,分别对应不同的关系约束。根据这些约束,我们可以构建一个差分约束图。图中的节点表示小朋友,边表示糖果数量的关系。根据不同的X值,我们可以添加相应的边和权重。然后,我们可以使用SPFA算法(Shortest Path Faster Algorithm)来求解这个差分约束系统,找到满足所有约束的最小糖果数量。 需要注意的是,在读取输入时需要判断X和Y是否合法,即是否满足X≠Y。如果X=Y,则直接输出-1,因为这种情况下无法满足约束条件。 综上所述,为了满足每个小朋友的要求,并且满足所有的约束条件,我们可以使用差分约束系统和SPFA算法来求解这个问题。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [【差分约束系统】【SCOI2011】糖果 candy](https://blog.csdn.net/jiangzh7/article/details/8872699)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [P3275 [SCOI2011]糖果(差分约束板子)](https://blog.csdn.net/qq_40619297/article/details/88678605)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值