zoukankan      html  css  js  c++  java
  • #3316. baka

    题目描述

    Worldwide_D最近沉迷东方。

    数学课上,Worldwide_D在研究对数,然后渐渐睡着了。他梦见自己躺在幻想乡的雾之湖边,听见旁边有两个妖精在对话,原来是Cirno和Daiyousei。

    Daiyousei:Cirno酱,我们趁着夜色,把整个幻想乡占领吧!

    Cirno:好啊!这样我们就可以到处玩了。

    不知道你们反应如何,反正听到这段对话,Worldwide_D是笑出来了。幻想乡可以看作n个节点的树,每条道路都是有向边。Cirno可以消耗一点灵力,改变一条道路的方向。

    如果最终得到的树满足:Daiyousei和Cirno各选一个节点(可以相同),然后出发能到达所有节点,那么幻想乡就算是被占领了。Cirno作为算术天才,开始算最少要消耗多少灵力。

    结果Worldwide_D等答案等了大半天,最后忍无可忍,大喊:这是什么SB题啊!!

    然后Worldwide_D醒来,发现自己身处数学课堂,全部人看着自己。

    现在你来解决这个问题吧!

    数据范围

    $n le 10^6$

    题解

    题目可以简化为改变一些边的方向,使得最后入读为 $0$ 的点不超过 $2$ 个,要求改变的边的数量最小

    考虑 $dp$ , $f_{i,1/2,0/1}$ 表示 $i$ 子树内,有 $1/2$ 个入度为 $0$ 的点,并且 $i$ 这个点不是/是入度为 $0$ 的点

    转移有点复杂,可以自己推下,具体参考代码

    效率: $O(n)$

    代码

    #include <bits/stdc++.h>
    using namespace std;
    const int N=1e6+5;
    int n,hd[N],V[N*2],nx[N*2],t,W[N*2];
    long long f[N][2][2],g[2][2];
    void add(int u,int v,int w){
        nx[++t]=hd[u];V[hd[u]=t]=v;W[t]=w;
    }
    void dfs(int x,int fr){
        for (int j=0;j<2;j++)
            for (int k=0;k<2;k++)
                f[x][j][k]=1e8;f[x][0][1]=0;
        for (int v,i=hd[x];i;i=nx[i])
            if ((v=V[i])!=fr){
                dfs(V[i],x);
                for (int j=0;j<2;j++)
                    for (int k=0;k<2;k++)
                        g[j][k]=f[x][j][k];
                f[x][0][0]=min(g[0][0]+f[v][0][1]+W[i],g[0][1]+min(f[v][0][0],f[v][0][1])+(W[i]^1));
                f[x][0][1]=g[0][1]+f[v][0][1]+W[i];
                f[x][1][0]=min(min(g[0][0]+min(min(f[v][0][0],f[v][1][1]+W[i]),f[v][0][1]+(W[i]^1)),g[0][1]+min(f[v][1][0],f[v][1][1])+(W[i]^1)),min(g[1][0]+f[v][0][1]+W[i],g[1][1]+min(f[v][0][0],f[v][0][1])+(W[i]^1)));
                f[x][1][1]=min(g[1][1]+f[v][0][1],g[0][1]+min(f[v][1][1],f[v][0][0]))+W[i];
            }
    }
    int main(){
        scanf("%d",&n);
        for (int x,y,i=1;i<n;i++)
            scanf("%d%d",&x,&y),
            add(x,y,0),add(y,x,1);
        dfs(1,0);printf("%lld
    ",min(min(f[1][0][0],f[1][0][1]),min(f[1][1][0],f[1][1][1])));
        return 0;
    }
  • 相关阅读:
    HDOJ 1846 Brave Game
    并查集模板
    HDU 2102 A计划
    POJ 1426 Find The Multiple
    POJ 3278 Catch That Cow
    POJ 1321 棋盘问题
    CF 999 C.Alphabetic Removals
    CF 999 B. Reversing Encryption
    string的基础用法
    51nod 1267 4个数和为0
  • 原文地址:https://www.cnblogs.com/xjqxjq/p/11327064.html
Copyright © 2011-2022 走看看