hdu6035_Colorful Tree_(树形DP)

来源:互联网 发布:mac world破解版 编辑:程序博客网 时间:2024/06/05 15:52
#include <iostream>#include <cstdio>#include <cstring>#include <algorithm>#include <cmath>#include <vector>#define INF 0x3f3f3f3f#define rep0(i, n) for (int i = 0; i < n; i++)#define rep1(i, n) for (int i = 1; i <= n; i++)#define rep_0(i, n) for (int i = n - 1; i >= 0; i--)#define rep_1(i, n) for (int i = n; i > 0; i--)#define MAX(x, y) (((x) > (y)) ? (x) : (y))#define MIN(x, y) (((x) < (y)) ? (x) : (y))#define mem(x, y) memset(x, y, sizeof(x))#define MAXN 200000 + 10/**题目大意树上每个节点有一个用数表示的颜色 定义一条路径的权值为路上出现的颜色的种类 计算树中所有路径的权值之和思路树上所有路径的权值和 = ∑路径颜色种类 = 每种颜色所经过的路径数直接计算每种颜色所经过的路径数非常非常困难 换了n种方法 死了一堆脑细胞 也还是出不来换个角度,计算每种颜色不经过次颜色的路径数就简单多了 ans = 颜色数 * 路径总数 - 每种颜色不经过的路径数*/using namespace std;typedef long long LL;int col[MAXN];vector<int> g[MAXN];void addEdge(int u, int v){    g[u].push_back(v);    g[v].push_back(u);}LL ans;    //各子树节点数int n, dp[MAXN];LL comb(int n){    return (LL)n * (n - 1) / 2;}int dfs(int u, int fa){    int myCol = col[u], num = 0, cnt = 0;    for (int i = 0; i < g[u].size(); i++)    {        int v = g[u][i];        if (v == fa)            continue;        int pre = dp[myCol], tmp;        tmp = dfs(v, u);        num += tmp;        cnt += dp[myCol] - pre;        ans -= comb(tmp - dp[myCol] + pre);    }    dp[myCol] += num + 1 - cnt;    return num + 1;}bool book[MAXN];int cols, colM;int main(){    #ifndef ONLINE_JUDGE        freopen("in.txt", "r", stdin);    #endif // ONLINE_JUDGE    int u, v, kase = 0;    while (scanf("%d", &n) != EOF)    {        mem(book, 0);        mem(dp, 0);        ans = 0;        colM = 0;        cols = 0;        for (int i = 1; i <= n; i++)        {            scanf("%d", col + i);            colM = MAX(colM, col[i]);            if (book[col[i]] == false)            {                book[col[i]] = true;                cols++;            }            g[i].clear();        }        for (int i = 0; i < n - 1; i++)        {            scanf("%d %d", &u, &v);            addEdge(u, v);        }        ans += (LL)cols * comb(n);        //cout << cols << endl;        dfs(1, 0);        for (int i = 1; i <= colM; i++)            if (book[i])                ans -= comb(n - dp[i]);        //cout << ans << endl;        //dfs1(1, 0);        printf("Case #%d: %lld\n", ++kase, ans);    }    return 0;}/*101 2 1 4 2 4 7 3 7 61 23 14 25 26 17 58 69 310 481 2 4 3 2 1 4 31 21 32 42 53 67 48 321 11 2121 1 1 1 1 1 1 1 1 1 1 11 21 31 42 52 63 74 84 96 106 118 1241 2 2 31 23 14 2*/

原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 土地局把我的档案弄丢了怎么办 人事关系在医院不去上班怎么办 档案年龄多处涂改无法退休怎么办 个人办理退休原始档案丢了怎么办 在钢厂工作想辞职了怎么办呢 场地合同到期了公司不续签怎么办 应届生没毕业找到工作怎么办入职 公司工资保密同事要看工资条怎么办 考上特岗教师后和老公异地怎么办 档案在无档案保管权限的公司怎么办 辞职了户口迁回农原籍不接收怎么办 当正职直接指挥下级副职领导怎么办 单位申报个税身份证号码填错怎么办 申报个税身份证号码填错了怎么办 办了人事代理联系函商调函怎么办 劳务公司与分包工头算账成怎么办 客户退保业务员己得保险佣金怎么办 投了简历公司打来电话没接到怎么办 跟老板要工资她说过几天怎么办 公路车弯把手小抓不到刹车怎么办 新手骑电动车上路车子一直晃怎么办 不知情收赃东西已经卖了怎么办 档案和派遣证不在同一个地方怎么办 档案缺招工表和派遣证怎么办退休 开发商对接的银行利息比较高怎么办 工作未满一年离职转正定级怎么办 被网络骗贷翻到几十万怎么办 面试通过后迟迟不通知入职怎么办 厂里捡到饭卡花了里面的钱怎么办 上班用自己手机打卡没电怎么办 逸尚考勤机显示超出考勤记录怎么办 下雨穿套裙工装上班好冷怎么办 蚂蚁借呗放款中不到账怎么办 护士电子化注册没有激活码怎么办? 地铁站务员入职体检身高差点怎么办 车子钥匙锁在车里了怎么办 打错账户了怎么办5天了 下岗失业人员在就业后档案怎么办 皮秒祛斑后没有敷面膜怎么办 硕士毕业工资好低不想工作怎么办 车卖了etc忘拿了怎么办