• POJ 3140 Contestants Division 树形DP


    题意:

    有一棵树,有点权,你可以选择一条边删除,要求删除后形成的2棵子树的权值的差的绝对值最小

    输出这个最小值

    本来是简单题,一个数组siz

    siz[i]表示以i为根的子树的节点的权值之和

    然后遍历一遍,找到最小值即可。

    注意:

    0.点权要long long

    1.由于点权之和是long long 的,你在求最小值的时候,初始化ret,

       要初始化为ret=0x3f3f3f3f3f3f3f3f,而不能是0x3f3f3f3f

    2.输入的数据描述的是n m

      (1 ≤ N ≤ 100000, 1 ≤ M ≤ 1000000)

      n表示节点的个数,m表示边的个数

      然后我就呆了,题目明明说了这是一棵树啊,也就是边数为n-1啊,这里弄个m<= 1000000是什么?

      然后想想才知道,这是唬人的,数据一定会保证m=n-1的,被骗了,然后还以为自己读错题意了,又看了很久的题目

    3.这里的abs()函数要自己写,因为cmath的abs()函数是int abs()的,在这里不适合,会CE

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    
    #define ll long long
    
    using namespace std;
    
    const int maxn=1e5+10;
    const ll inf=0x3f3f3f3f3f3f3f3f;
    
    struct Edge
    {
        int to,next;
    };
    Edge edge[maxn<<1];
    int tot;
    int head[maxn];
    
    ll val[maxn];
    ll siz[maxn];
    ll sum;
    
    void init()
    {
        memset(head,-1,sizeof head);
        tot=0;
        sum=0;
    }
    
    void addedge(int u,int v)
    {
        edge[tot].to=v;
        edge[tot].next=head[u];
        head[u]=tot++;
    }
    
    ll solve(int );
    
    int main()
    {
        int cas=1;
        int n,m;
        while(scanf("%d %d",&n,&m)){
            if(!n&&!m)
                break;
            printf("Case %d: ",cas++);
            init();
            for(int i=1;i<=n;i++){
                scanf("%lld",&val[i]);
                sum+=val[i];
            }
    
            for(int i=1;i<=m;i++){
                int u,v;
                scanf("%d %d",&u,&v);
                addedge(u,v);
                addedge(v,u);
            }
            printf("%lld
    ",solve(n));
        }
        return 0;
    }
    
    void dfs(int u,int pre)
    {
        siz[u]=val[u];
        for(int i=head[u];~i;i=edge[i].next){
            int v=edge[i].to;
            if(v==pre)
                continue;
            dfs(v,u);
            siz[u]+=siz[v];
        }
    }
    
    ll solve(int n)
    {
        //printf("eee
    ");
        dfs(1,-1);
    
        ll ret=inf;
        for(int i=2;i<=n;i++){
            ll cnt=sum-2*siz[i];
            if(cnt<0)
                cnt*=(-1);
            if(cnt<ret)
                ret=cnt;
        }
        return ret;
    }
  • 相关阅读:
    OJ生成器(一)制作Online Judge前的准备和策划
    中国剩余定理
    图片
    扩展GCD的一点心得
    用css控制连续英文字符或数字换行
    CTFHUB HTTP协议之请求方式
    PHP基础05---文件处理
    PHP基础04---文件包含
    PHP基础03---数组
    PHP基础01
  • 原文地址:https://www.cnblogs.com/-maybe/p/4825885.html
Copyright © 2020-2023  润新知