• 【JZOJ5776】小x游世界【换根法】【DP】【DFS】


    题目大意:

    题目链接:https://jzoj.net/senior/#main/show/5776
    题目图片:
    http://wx4.sinaimg.cn/mw690/0060lm7Tly1fvjhzcpt7jj30j50f1aaw.jpg
    http://wx1.sinaimg.cn/mw690/0060lm7Tly1fvjhzchmayj30j30e5t8x.jpg
    http://wx4.sinaimg.cn/mw690/0060lm7Tly1fvjhzby695j30j506imx7.jpg


    思路:

    P.S.这道题题目描述太难写而我语文太菜没法简化所以各位大大就看图片吧orz。
    这道题,我们先跑一边DFS,求出以1为根的时候的答案和每个点的子树节点数量(含自己)。
    然后利用换根法(听说属于树形DP?),可以O(1)O(1)求出每个点为根的时候的答案。最后取一个最优答案即可。


    代码:

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #define N 701000
    #define ll long long
    using namespace std;
    
    int n,c[N],head[N],son[N],u,tot=1;
    ll sum[N],ans;
    char ch;
    
    struct edge
    {
    	int next,to,dis;
    }e[N*2];
    
    int read()  //不加快读会T
    {
        u=0;
        while((ch=getchar())<=47||ch>=58);u=(u<<3)+(u<<1)+ch-48;
        while((ch=getchar())>=48&&ch<=57) u=(u<<3)+(u<<1)+ch-48;
        return u;
    }
    
    void add(int from,int to,int dis)
    {
    	e[++tot].to=to;
    	e[tot].dis=dis;
    	e[tot].next=head[from];
    	head[from]=tot;
    }
    
    int dfs(int x,ll k,int fa)  //DFS
    {
    	int s=1;
    	sum[1]+=k;  //sum[i]表示以第i个点为根的答案
    	for (int i=head[x];~i;i=e[i].next)
    	 if (e[i].to!=fa)
    	  s+=dfs(e[i].to,k+(ll)e[i].dis,x);
    	son[x]=s;  //son[x]表示以x为根的子树的节点数(含自己)
    	return s;
    }
    
    void change(int x,int fa)  //换根
    {
    	for (int i=head[x];~i;i=e[i].next)
    	 if (e[i].to!=fa)
    	 {
    	 	int y=e[i].to;
    	 	sum[y]=sum[x]-(ll)son[y]*(ll)e[i].dis+(ll)(son[1]-son[y])*(ll)e[i^1].dis;
    	 	//有些点要增加路径,而有些点要减少
    	 	change(y,x);
    	 }
    }
    
    int main()
    {
    	memset(head,-1,sizeof(head));
    	n=read();
    	for (int i=1;i<=n;i++)
    	 c[i]=read();
    	int x,y,z;
    	for (int i=1;i<n;i++)
    	{
    		x=read();
    		y=read();
    		z=read();
    		add(x,y,z-c[x]);
    		add(y,x,z-c[y]);
    	}
    	dfs(1,0,-666);
    	change(1,-666);
    	ans=1e17;
    	for (int i=1;i<=n;i++)
    	 if (sum[i]<ans)  //取最小值
    	 {
    	 	ans=sum[i]; 
    	 	x=i;
    	 }
    	cout<<x<<"\n"<<ans;
    	return 0;
    }
    
  • 相关阅读:
    深入NET框架
    解决idea中maven的pom文件不会自动下载jar包问题
    JSP中的作用域
    转发与重定向
    JSP内置对象
    JNDI与连接池
    文件上传
    七大设计原则
    第六章 初始继承和多态
    C#和.NET框架
  • 原文地址:https://www.cnblogs.com/hello-tomorrow/p/11998561.html
Copyright © 2020-2023  润新知