• [SCOI2012]滑雪与时间胶囊


    题目大意:
      给你一个带边权图,每个点都有自己的高度h[i],结点只能通过边到达高度不高于它的结点j。
      你可以通过某种手段跳转到你原来走过的结点,不计入路径。
      问你从1号点出发,最多可以到达多少点?路径和最小是多少?

    思路:
      对于第一问,我们可以bfs一边把所有能走到的地方遍历一遍。
      对于第二问,实际上就是在上一问遍历的点中找一个最小树形图。
      如果我们把这些结点按照高度分成很多“层”,那么我们需要首先保证高的点连了边(后面低的就算不连边也可以从高的跳转过去)。
      所以我们对于边集,先按照高度从大到小排序,再按照边权升序排序,跑一边Kruskal即可。

     1 #include<queue>
     2 #include<cstdio>
     3 #include<cctype>
     4 #include<cstring>
     5 #include<algorithm>
     6 typedef long long int64;
     7 inline int getint() {
     8     register char ch;
     9     while(!isdigit(ch=getchar()));
    10     register int x=ch^'0';
    11     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
    12     return x;
    13 }
    14 const int N=100001,M=2000001;
    15 int h[N];
    16 struct Edge {
    17     int from,to,w,next;
    18     bool operator < (const Edge &another) const {
    19         if(h[to]==h[another.to]) return w<another.w;
    20         return h[to]>h[another.to];
    21     }
    22 };
    23 Edge e[M];
    24 int head[N],cnt;
    25 inline void add_edge(const int &u,const int &v,const int &w) {
    26     e[cnt]=(Edge){u,v,w,head[u]};
    27     head[u]=cnt++;
    28 }
    29 int ans1;
    30 bool vis[N];
    31 inline void bfs() {
    32     static std::queue<int> q;
    33     q.push(1);
    34     vis[1]=true;
    35     while(!q.empty()) {
    36         const int x=q.front();
    37         q.pop();
    38         ans1++;
    39         for(register int i=head[x];~i;i=e[i].next) {
    40             const int &y=e[i].to;
    41             if(vis[y]) continue;
    42             vis[y]=true;
    43             q.push(y);
    44         }
    45     }
    46 }
    47 class DisjointSet {
    48     private:
    49         int anc[N];
    50         int find(const int &x) {
    51             return x==anc[x]?x:anc[x]=find(anc[x]);
    52         }
    53     public:
    54         DisjointSet() {
    55             for(register int i=1;i<N;i++) {
    56                 anc[i]=i;
    57             }
    58         }
    59         void Union(const int &x,const int &y) {
    60             anc[find(x)]=find(y);
    61         }
    62         bool isConnected(const int &x,const int &y) {
    63             return find(x)==find(y);
    64         }
    65 };
    66 DisjointSet s;
    67 int main() {
    68     const int n=getint(),m=getint();
    69     for(register int i=1;i<=n;i++) {
    70         h[i]=getint();
    71     }
    72     memset(head,-1,sizeof head);
    73     for(register int i=1;i<=m;i++) {
    74         const int u=getint(),v=getint(),w=getint();
    75         if(h[u]>=h[v]) add_edge(u,v,w);
    76         if(h[v]>=h[u]) add_edge(v,u,w);
    77     }
    78     bfs();
    79     std::sort(&e[0],&e[cnt]);
    80     int64 ans2=0;
    81     for(register int i=0;i<cnt;i++) {
    82         const int &u=e[i].from,&v=e[i].to,&w=e[i].w;
    83         if(!vis[u]||!vis[v]) continue;
    84         if(s.isConnected(u,v)) continue;
    85         s.Union(u,v);
    86         ans2+=w;
    87     }
    88     printf("%d %lld
    ",ans1,ans2);
    89     return 0;
    90 }
  • 相关阅读:
    linux进程cpu使用率过高分析与排查
    重启服务器后keepalived,vip找不到
    linux五种IO模型
    redis为什么单线程这么快?
    nginx为什么比apache快?
    redis高可用,主从,哨兵,集群
    git合并远端commit
    查看cpu和内存
    CommitLog文件和ConsumeQueue在文件系统中的映射
    hadoop集群启动
  • 原文地址:https://www.cnblogs.com/skylee03/p/7766292.html
Copyright © 2020-2023  润新知