• 【BZOJ】2435: [Noi2011]道路修建(树形dp)


    http://www.lydsy.com/JudgeOnline/problem.php?id=2435

    我怎么感觉那么水。。

    坑的是,dfs会爆。。。好吧。。用bfs。。

    //upd:我的智商也是醉了。。。。判断另一个图的节点个数不就是n-size么。。。。。。。。。我为嘛那么sb

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    #include <queue>
    #include <set>
    #include <map>
    using namespace std;
    typedef long long ll;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << (#x) << " = " << (x) << endl
    #define error(x) (!(x)?puts("error"):0)
    #define rdm(x, i) for(int i=ihead[x]; i; i=e[i].next)
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    
    const int N=1000005;
    int s[N], cnt, ihead[N], q[N], vis[N], h[N], in[N], n;
    ll ans;
    struct dat { int next, to, w; }e[N<<1];
    void add(int u, int v, int w) { 
    	e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v; e[cnt].w=w;
    	e[++cnt].next=ihead[v]; ihead[v]=cnt; e[cnt].to=u; e[cnt].w=w;
    }
    int bfs1() {
    	int front=0, tail=0;
    	for1(i, 1, n) if(in[i]==1) q[tail++]=i;
    	while(front!=tail) {
    		int x=q[front++]; vis[x]=1; s[x]++;
    		rdm(x, i) if(!vis[e[i].to]) {
    			int y=e[i].to;
    			s[y]+=s[x];
    			if(--in[y]==1) q[tail++]=y;
    		}
    	}
    	return q[front-1];
    }
    void bfs2(int x) {
    	for1(i, 1, n) vis[i]=0;
    	int front=0, tail=0;
    	q[tail++]=x;
    	while(front!=tail) {
    		x=q[front++]; vis[x]=1;
    		int ss=h[x], sum=s[x];
    		rdm(x, i) if(!vis[e[i].to]) {
    			int y=e[i].to;
    			ans+=1ll*e[i].w*abs(ss+sum-s[y]-s[y]);
    			h[y]=ss+sum-s[y];
    			q[tail++]=y;
    		}
    	}
    }
    int main() {
    	read(n);
    	for1(i, 1, n-1) { int u=getint(), v=getint(), w=getint(); add(u, v, w); in[u]++; in[v]++; }
    	bfs2(bfs1());
    	printf("%lld
    ", ans);
    	return 0;
    }
    

      


    Description

    在 W 星球上有 n 个国家。为了各自国家的经济发展,他们决定在各个国家
    之间建设双向道路使得国家之间连通。但是每个国家的国王都很吝啬,他们只愿
    意修建恰好 n – 1条双向道路。 每条道路的修建都要付出一定的费用, 这个费用等于道路长度乘以道路两端的国家个数之差的绝对值。例如,在下图中,虚线所示道路两端分别有 2 个、4个国家,如果该道路长度为 1,则费用为1×|2 – 4|=2。图中圆圈里的数字表示国家的编号。


    由于国家的数量十分庞大,道路的建造方案有很多种,同时每种方案的修建
    费用难以用人工计算,国王们决定找人设计一个软件,对于给定的建造方案,计
    算出所需要的费用。请你帮助国王们设计一个这样的软件。

    Input


    输入的第一行包含一个整数n,表示 W 星球上的国家的数量,国家从 1到n
    编号。接下来 n – 1行描述道路建设情况,其中第 i 行包含三个整数ai、bi和ci,表
    示第i 条双向道路修建在 ai与bi两个国家之间,长度为ci。

    Output

    输出一个整数,表示修建所有道路所需要的总费用。

    Sample Input


    6
    1 2 1
    1 3 1
    1 4 2
    6 3 1
    5 2 1

    Sample Output


    20

    HINT



    n = 1,000,000 1≤ai, bi≤n 

    0 ≤ci≤ 10^6

     

    Source

  • 相关阅读:
    使用jquery.validate.js实现boostrap3的校验和验证
    MySQL 随机取数据效率问题
    qq在线客服代码
    使用Shell脚本查找程序对应的进程ID,并杀死进程
    Redis-概述
    JVM的类加载机制
    volatile
    java内存相关
    设计模式--模板方法
    设计模式概述
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/4153669.html
Copyright © 2020-2023  润新知