zoukankan      html  css  js  c++  java
  • P4149 [IOI2011]Race

    题目

    P4149 [IOI2011]Race

    给一棵树,每条边有权。求一条简单路径,权值和等于 (k),且边的数量最小,求最小个数。

    分析

    第一问很简单,我们只需要判定即可。

    第二问我们其实可以考虑在第一问基础上记录这样的信息:用桶记录值等于当前权值的,且边最小的条数

    然后就可以和模板一样匹配了,只不过那里是统计个数,这里是拼最小值。

    代码

    #include<bits/stdc++.h>
    using namespace std;
    template <typename T>
    inline void read(T &x){
        x=0;char ch=getchar();bool f=false;
        while(!isdigit(ch)) f|=ch=='-',ch=getchar();
        while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
        x=f?-x:x;return;
    }
    template <typename T>
    inline void write(T x){
        if(x<0) putchar('-'),x=-x;
        if(x>9) write(x/10);
        putchar(x%10^48);return;
    }
    #define ll long long
    const int N=5e5+5,M=1e7+5,INF=INT_MAX;
    int n,m;
    int head[N],nex[N],to[N],val[N],idx;
    bool vis[N],Vis[N];
    int app[M],Ans;
    int siz[N];
    struct Edge{int dis,num,node;}path[N],clear[N];
    int Root,NowMax,path_cnt,Cnt,Size;
    inline void add(int u,int v,int w){
    	nex[++idx]=head[u];
    	to[idx]=v;
    	val[idx]=w;
    	head[u]=idx;
    	return ;
    }
    void FindRoot(int x){
    	vis[x]=true;siz[x]=1;int Max=0;
    	for(int i=head[x];i;i=nex[i]){
    		int y=to[i];
    		if(vis[y]||Vis[y]) continue;
    		FindRoot(y);siz[x]+=siz[y];
    		Max=max(siz[y],Max);
    	}
    	Max=max(Size-siz[x],Max);
    	if(Max<=NowMax) NowMax=Max,Root=x;
    	vis[x]=false;
    	return ;
    }
    void GetPath(int x,int D,int num){
    	path[++path_cnt].dis=D,path[path_cnt].num=num,path[path_cnt].node=x;vis[x]=true;
    	for(int i=head[x];i;i=nex[i]){
    		int y=to[i];
    		if(vis[y]||Vis[y]) continue;
    		GetPath(y,D+val[i],num+1);
    	}
    	vis[x]=false;
    	return ;
    }
    void DFS(int x){
    	Vis[x]=true;Cnt=0;
    	for(int i=head[x];i;i=nex[i]){
    		int y=to[i];
    		if(Vis[y]) continue;
    		path_cnt=0;GetPath(y,val[i],1);
    		for(int k=1;k<=path_cnt;k++) if(m>=path[k].dis&&app[m-path[k].dis]!=INF) Ans=min(Ans,app[m-path[k].dis]+path[k].num);
    		for(int j=1;j<=path_cnt;j++) if(path[j].dis<=m) app[path[j].dis]=min(app[path[j].dis],path[j].num),clear[++Cnt]=path[j];
    	}
    	for(int i=1;i<=Cnt;i++) app[clear[i].dis]=INF;
    	for(int i=head[x];i;i=nex[i]){
    		int y=to[i];
    		if(Vis[y]) continue;
    		Size=siz[y],NowMax=n,Root=0,FindRoot(y);DFS(Root);
    	}
    	return ;
    }
    signed main(){
    	read(n),read(m);
    	for(int i=1;i<n;i++){
    		int u,v,w;
    		read(u),read(v),read(w);u++,v++;
    		add(u,v,w),add(v,u,w);
    	}
    	for(int i=1;i<=m;i++) app[i]=INF;
    	app[0]=0;Ans=INF;
    	Size=n,NowMax=n,Root=0,FindRoot(1),DFS(Root);
    	write(Ans!=INF?Ans:-1);
    	return 0;
    }
    
  • 相关阅读:
    Vue技巧小结(持续更新)
    Vue+Webpack常见问题(持续更新)
    webpack模块定义和使用的模式
    vue-cli笔记
    新浪微博怎么知道你没登录
    jquery页面水印插件,支持多行水印、行错开
    浏览器并发连接数(未完成)
    HTTP1.0 、1.1
    你总说时间很少
    看小说的这些年
  • 原文地址:https://www.cnblogs.com/Akmaey/p/14726828.html
Copyright © 2011-2022 走看看