zoukankan      html  css  js  c++  java
  • 题解 P2573 【[SCOI2012]滑雪】

    题目链接

    Solution [SCOI2012]滑雪

    题目大意:给你一个图,每个点有一个高度,你只能从一个点走向高度不大于它的点,求在可以走的点最多的限制下的最小权值和

    最小生成树,贪心


    分析:如果不考虑高度限制,这题实质上是一个最小生成树,关键在于考虑上高度限制

    既然要使得走到的点最多,显然我们优先从一个点走向它可以走的点集里面高度最高的点,这样可以使得答案最优.然后在这个基础上使得权值之和最小

    可以用类似(Prim)算法求解,朴素(Prim)从可以扩展的点集(V)里面选择离生成树最近的点扩展,这里选择高度最大的点扩展,如果高度一样选择离生成树最近的即可

    貌似还可以用(Kruskal?),不过感觉不是很直观的样子(主要是(TCL))

    代码:

    #include <cstdio>
    #include <cstring>
    #include <cctype>
    #include <queue>
    using namespace std;
    typedef long long ll;
    const int maxn = 1e5 + 100,maxm = 2e6 + 100;
    inline int read(){
    	int x = 0;char c = getchar();
    	while(!isdigit(c))c = getchar();
    	while(isdigit(c))x = x * 10 + c - '0',c = getchar();
    	return x;
    }
    struct Edge{
    	int from,to,dist;
    }Edges[maxm];
    int head[maxn],nxt[maxm],n,m;
    inline void addedge(int from,int to,int dist){
    	static int tot;
    	Edges[++tot] = Edge{from,to,dist};
    	nxt[tot] = head[from];
    	head[from] = tot;
    }
    int high[maxn];
    ll ans1,ans2;
    int dis[maxn],vis[maxn];
    struct Point{
    	int u,high,dis;
    	bool operator < (const Point &rhs)const{
    		return (high == rhs.high) ? (dis > rhs.dis) : (high < rhs.high);
    	}
    };
    priority_queue<Point> Q;
    int main(){
    	n = read(),m = read();
    	for(int i = 1;i <= n;i++)high[i] = read();
    	for(int u,v,d,i = 1;i <= m;i++)
    		u = read(),v = read(),d = read(),addedge(u,v,d),addedge(v,u,d);
    	memset(dis,0x3f,sizeof(dis));
    	dis[1] = 0;Q.push(Point{1,high[1],dis[1]});
    	while(!Q.empty()){
    		Point p = Q.top();Q.pop();
    		int u = p.u;
    		if(vis[u])continue;
    		vis[u] = 1;
    		ans1++;
    		ans2 += dis[u];
    		for(int i = head[u];i;i = nxt[i]){
    			int v = Edges[i].to;
    			if(vis[v])continue;
    			if(high[u] < high[v])continue;
    			if(Edges[i].dist < dis[v]){
    				dis[v] = Edges[i].dist;
    				Q.push(Point{v,high[v],dis[v]});
    			}
    		}
    	}
    	printf("%lld %lld
    ",ans1,ans2);
    	return 0;
    }
    
  • 相关阅读:
    [ 低危 ] mt网CRLF
    mysql之字段的修改,添加、删除,多表关系(外键),单表详细操作(增删改)
    mysql 之编码配置、引擎介绍、字段操作、数据类型及约束条件
    Navicat Premium永久激活方式
    centos 用户名密码忘记了怎么办?
    并发编程总结
    初识mysql
    线程queue、线程进程池,协程
    python解释器
    线程全局修改、死锁、递归锁、信号量、GIL以及多进程和多线程的比较
  • 原文地址:https://www.cnblogs.com/colazcy/p/11522794.html
Copyright © 2011-2022 走看看