[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 }
原文地址:https://www.cnblogs.com/skylee03/p/7766292.html