zoukankan      html  css  js  c++  java
  • 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;
    }
  • 相关阅读:
    [Android教程]通过Intent分享数据内容给其他应用程序
    【Android您问我讲】Android 2.x中使用actionbar Actionbarsherlock的使用
    PHP按比例生成縮略圖片
    PHP實現任務計畫
    javascript下漢字和Unicode編碼互轉代碼
    js存/讀取cookie函數
    php Captcha 練習
    PHP概率抽獎
    讓iframe自適應高度
    簡單的 PHP 將sql文件導入數據庫程序
  • 原文地址:https://www.cnblogs.com/-maybe/p/4825885.html
Copyright © 2011-2022 走看看