[SCOI2012]滑雪与时间胶囊

本文探讨了一种特定的图论问题,即在一个带边权且结点有高度限制的图中,从起始结点出发可达的最大结点数及路径最小权值和。通过BFS搜索算法确定可达结点,并利用Kruskal算法找到最小生成树,从而得到最优解。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目大意:
  给你一个带边权图,每个点都有自己的高度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\n",ans1,ans2);
89     return 0;
90 }

 

转载于:https://www.cnblogs.com/skylee03/p/7766292.html

中描述了一个幼儿园里分配糖果的问题,每个小朋友都有自己的要求。问题的输入包括两个整数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.youkuaiyun.com/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.youkuaiyun.com/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、付费专栏及课程。

余额充值