• P5021赛道修建题解


    题目戳我

    看到最小值最大,很容易想到二分。
    那么我们想想怎么(check)

    在找路径的时候,显然让路径越接近要(check)(mid)就越好。而且我们不能漫无目的的凑,要找个神奇的顺序,所以我们不妨使用(dfs)

    (dfs)时,对于每一个节点,考虑它所有连着儿子的边。如果这条边的长度大于(mid),那么它本身就可以成为一条路径。反之,则找到另一条边(j),使得(dis[i]+dis[j]>=mid)且不存在边(k)使得(dis[i]+dis[k]geqslant mid)(&&)(dis[k]<dis[j])

    如果还有剩下的边,那就考虑把这些边中最大的边接到当前节点上。

    这些操作可以用(multiset)搞定(当然我写丑了要吸氧)

    有关(multiset)

    (multiset)就是可以有重复元素的(set)
    常用函数:

    multiset<int> q;
    将x插入进multiset: q.insert(x)
    
    删除所有值为x的元素: q.erase(x)
    
    删除x这个位置的元素(此时x为迭代器): q.erase(x)
    
    删除[l,r)这一段的元素: q.erase(l,r)
    
    第一个元素的位置: q.begin()
    
    最后一个元素的后一个位置: q.end()
    
    最后一个元素的位置: q.rbegin()
    
    第一个元素的前一个位置: q.rend()
    
    寻找值为x的元素的位置: q.find(x)(找不到返回q.end())
    
    找到第一个大于等于x的元素的位置: q.lower_bound(x)(失败返回q.end())
    
    找第一个大于x的元素的位置: q.upper_bound(x)(失败返回q.end())
    
    判空: q.empty()
    
    清空: q.clear()
    

    (Code)(要开(c++11)以及吸氧)

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cstdlib>
    #include<algorithm>
    #include<cmath>
    #include<queue>
    #include<vector>
    #include<ctime>
    #include<deque>
    #include<set>
    #define pa pair<int,int>
    #define rg register
    #define ls (k<<1)
    #define rs (k<<1|1)
    using namespace std;
    typedef long long ll;
    const double eps=1e-13;
    inline int read(){
    	char ch=getchar();
        int x=0;bool f=0;
    	while(ch<'0'||ch>'9')
    	{
    		if(ch=='-') f=1;
    		ch=getchar();
    	}
    	while(ch>='0'&&ch<='9')
    	{
    		x=(x<<3)+(x<<1)+(ch^48);
    		ch=getchar();
    	}
    	return f?-x:x;
    }
    const int N=50009;
    int n,m,head[N],cnt,l=2147483647,r,rtn;
    struct E{
    	int to,nxt,dis;
    }ed[N<<1];
    inline void add(int fr,int to,int dis){
    	ed[++cnt].to=to;
    	ed[cnt].dis=dis;
    	ed[cnt].nxt=head[fr];
    	head[fr]=cnt;
    }	
    int dfs(int u,int f,int x){
            multiset<int> q;
    	for(rg int e=head[u];e;e=ed[e].nxt){
    		int v=ed[e].to;
    		if(v==f) continue;
    		int d=ed[e].dis+dfs(v,u,x);
    		if(d>=x) rtn++;//rtn统计找到的路径条数
    		else q.insert(d);
    	}
    	if(q.empty()) return 0;
    	int rr=0;
    	while(!q.empty()){
    		auto i=q.begin();
    		int d=x-*i,qwq=*i;
    		q.erase(i);//注意先删除当前元素,这样才能准确知道是否有和这个元素相等的符合条件的元素
    		auto j=q.lower_bound(d);
    		if(j==q.end()) rr=max(rr,qwq);//选择最长的接上去
    		else{
    			rtn++;
    			q.erase(j);
    		}
    	}
    	return rr;//返回接上去的长度
    }
    inline bool ck(int x){
    	  rtn=0;
    	  int orz=dfs(1,0,x);
    	  if(rtn>=m) return 1;
    	  return 0;
    }
    int main(){
    	n=read();m=read();
    	for(rg int i=1;i<n;i++){
    		int fr=read(),to=read(),dis=read();
    		add(fr,to,dis);add(to,fr,dis);
    		r+=dis;l=min(l,dis);
    	}
    	r/=m;//讨论区大佬神奇的优化
    	while(l<=r){
    		int mid=(l+r)>>1;
    		if(ck(mid)) l=mid+1;
    		else r=mid-1;
    	}
    	printf("%d
    ",r);
    }
    
  • 相关阅读:
    Scrapy+Scrapy-redis+Scrapyd+Gerapy 分布式爬虫框架整合
    centos7 安装软件指南
    Kafka--消费者
    Kafka--生产者
    Kafka--初识Kafka
    Kafka--Kafka简述
    NetWork--记一次Http和TLS抓包
    JVM--a == (a = b)基于栈的解释器执行过程
    Java容器--Queue
    Idea--使用Idea调试设置
  • 原文地址:https://www.cnblogs.com/lcez56jsy/p/13617062.html
Copyright © 2020-2023  润新知