• 洛谷 P2573 [SCOI2012]滑雪


    题目描述

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

    胶囊消耗的情况下,以最短滑行距离滑到尽量多的景点的方案(即满足经过景点数最大的前提下使得滑行总距离最小)。你能帮他求出最短距离和景点数吗?

    输入输出格式

    输入格式:

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

    接下来1行有N个整数Hi,分别表示每个景点的高度。

    接下来M行,表示各个景点之间轨道分布的情况。每行3个整数,Ui,Vi,Ki。表示

    编号为Ui的景点和编号为Vi的景点之间有一条长度为Ki的轨道。

    输出格式:

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

    输入输出样例

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

    说明

    【数据范围】

    对于30%的数据,保证 1<=N<=2000

    对于100%的数据,保证 1<=N<=100000

    对于所有的数据,保证 1<=M<=1000000,1<=Hi<=1000000000,1<=Ki<=1000000000。

    这题目的题意真是看不懂

    大概意思是给出一张有向图,边的方向是从高到低,让你求一个最小树形图

    朱刘算法怒艹1e13也不是不可以啊

    这道题的思路确实很妙,没看题解想不到

    首先观察发现能到达的点就是一遍BFS,这些点肯定都要到达

    然后走过的路径是一个以1为根的最小树形图

    直接朱刘算法肯定不行,需要考虑别的办法

    这张图的的性质是边只从高连向低,同高度之间是无向边

    如果把点按照高度分层,那么有向边只从高的一层连向低的一层,层内只有无向边

    这有什么用呢?

    我们知道,对于无向图的树形图(即生成树),有很优秀的办法来解决,为什么kruskal和prim不能做有向图的树形图呢?稍微尝试几个例子以后会发现,如果用无向图的方法来做,会有两个问题

    1、答案不是最优,这是由于prim的加入顺序问题导致的

    2、做出来的根本不是树形图,kruskal没法处理这种情况

    但是对于DAG这种特殊的图而言,无向图的方法加上一些魔改就可以做了,对于kruskal而言,把边按照终点的拓扑序为第一关键字,边长为第二关键字排序,然后往里加就行了

    让我们回到这道题的图,我们发现这张图很像是一层层的DAG加上层内的无向图,是不是胡搞一下就好了啊?

    发现是的,一样这么做就行,第一关键字h降序,第二关键字边长升序,原因是这样既不会产生第一个问题(按顺序一层层加入,答案不会变劣),也不会产生第二个问题(层间不会有问题,层内是无向边,可以随意分配)

    然后跑kruskal即可

      1 #include <iostream>
      2 #include <cstdlib>
      3 #include <cstdio>
      4 #include <algorithm>
      5 #include <string>
      6 #include <cstring>
      7 #include <cmath>
      8 #include <map>
      9 #include <stack>
     10 #include <set>
     11 #include <vector>
     12 #include <queue>
     13 #include <time.h>
     14 #include <functional>
     15 #define eps 1e-7
     16 #define INF 0x3f3f3f3f
     17 #define MOD 1000000007
     18 #define rep0(j,n) for(int j=0;j<n;++j)
     19 #define rep1(j,n) for(int j=1;j<=n;++j)
     20 #define pb push_back
     21 #define set0(n) memset(n,0,sizeof(n))
     22 #define ll long long
     23 #define ull unsigned long long
     24 #define iter(i,v) for(edge *i=head[v];i;i=i->nxt)
     25 #define max(a,b) (a>b?a:b)
     26 #define min(a,b) (a<b?a:b)
     27 #define print_runtime printf("Running time:%.3lfs
    ",double(clock())/1000.0)
     28 #define TO(j) printf(#j": %d
    ",j);
     29 //#define OJ
     30 using namespace std;
     31 const int MAXINT = 100010;
     32 const int MAXNODE = 100010;
     33 const int MAXEDGE = 4 * 1000010;
     34 char BUF, *buf;
     35 int read() {
     36     char c = getchar(); int f = 1, x = 0;
     37     while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
     38     while (isdigit(c)) {x = x * 10 + c - '0'; c = getchar();}
     39     return f * x;
     40 }
     41 char get_ch() {
     42     char c = getchar();
     43     while (!isalpha(c)) c = getchar();
     44     return c;
     45 }
     46 //------------------- Head Files ----------------------//
     47 int cnt, n, m;
     48 int vis[MAXNODE],ans,h[MAXNODE],qu[MAXNODE],fa[MAXNODE];
     49 struct edge {
     50     int u, v, l;
     51     edge *nxt;
     52     edge(int _u, int _v, int _l, edge * _nxt): u(_u), v(_v), l(_l), nxt(_nxt) {}
     53     edge() {}
     54 } mp[MAXEDGE], *head[MAXNODE];
     55 bool operator < (const edge &a,const edge &b){
     56     return h[a.v]==h[b.v]?a.l<b.l:h[a.v]>h[b.v];
     57 }
     58 void get_input();
     59 void work();
     60 void addedge(int u, int v,int l) {
     61     mp[cnt] = edge(u, v, l,head[u]);
     62     head[u] = &mp[cnt++];
     63 }
     64 /*void spfa(int ss, int tt) {
     65     memset(dis, 0x3f, sizeof(dis));
     66     dis[ss] = 0;
     67     int *h, *t;
     68     h = t = q;
     69     *t++ = ss;
     70     while (h != t) {
     71         int p = *h++; inq[p] = 0;
     72         iter(i, p) {
     73             if (dis[i->v] > dis[p] + i->l) {
     74                 dis[i->v] = dis[p] + i->l;
     75                 if (!inq[i->v]) {
     76                     *t++ = i->v;
     77                     inq[i->v] = 1;
     78                 }
     79             }
     80         }
     81     }
     82 }*/
     83 /*void dijkstra(int ss,int tt){
     84     memset(dis,0x3f,sizeof(dis));
     85     dis[ss]=0;
     86     q.push(make_pair(0,ss));
     87     int T=n-1;
     88     while(T--){
     89         while(!q.empty()&&vis[q.top().second]) q.pop();
     90         if(q.empty()) break;
     91         int p = q.top().second;q.pop();
     92         iter(i,p){
     93             if(dis[i->v]>dis[p]+i->l){
     94                 dis[i->v]=dis[p]+i->l;
     95                 q.push(make_pair(dis[i->v],i->v));
     96             }
     97         }
     98     }
     99 }*/
    100 void bfs(int p){
    101     int *h,*t;
    102     h=t=qu;
    103     vis[1]=1;ans=1;
    104     *t++=1;
    105     while(h!=t){
    106         int p=*h++;
    107         iter(i,p){
    108             if(!vis[i->v]) {vis[i->v]=1;ans++;*t++=i->v;}
    109         }
    110     }
    111 }
    112 int findfa(int p) {return p==fa[p]?p:fa[p]=findfa(fa[p]);}
    113 int main() {
    114     get_input();
    115     work();
    116     return 0;
    117 }
    118 void work() {
    119     //dijkstra(1,n);
    120     bfs(1);
    121     rep1(i,n) fa[i]=i;
    122     sort(mp,mp+cnt);
    123     ull sum=0;
    124     rep0(i,cnt){
    125         int u=mp[i].u,v=mp[i].v;
    126         if(!vis[u]||!vis[v]) continue;
    127         u=findfa(u);v=findfa(v);
    128         if(u!=v) {fa[u]=v; sum+=mp[i].l;}
    129     }
    130     printf("%d %llu
    ",ans,sum);
    131 }
    132 void get_input() {
    133     n = read(); m = read();
    134     rep1(i, n) h[i] = read();
    135     rep0(i, m) {
    136         int u = read(), v = read(), l = read();
    137         if (h[u] > h[v]) addedge(u, v, l);
    138         if (h[u] == h[v]) {addedge(u, v, l); addedge(v, u, l);}
    139         if (h[u] < h[v]) addedge(v, u, l);
    140     }
    141 
    142 }
  • 相关阅读:
    EL表达式
    Java反射机制详解
    最小生成树-Prim算法和Kruskal算法
    最短路径—Dijkstra算法和Floyd算法
    servlet的转发与重定向
    SQL常用增删改查
    Java map遍历
    深入理解Java的接口和抽象类
    eclipse快捷键
    Vue父子组件数据双向绑定,子组件可修改props
  • 原文地址:https://www.cnblogs.com/LoveYayoi/p/6925899.html
Copyright © 2020-2023  润新知