[贪心]JZOJ 3230 【佛山市选2013】树环转换

Description

给定一棵N个节点的树,去掉这棵树的一条边需要消耗值1,为这个图的两个点加上一条边也需要消耗值1。树的节点编号从1开始。在这个问题中,你需要使用最小的消耗值(加边和删边操作)将这棵树转化为环,不允许有重边。

环的定义如下:

(1)该图有N个点,N条边。

(2)每个顶点的度数为2。

(3)任意两点是可达的。

树的定义如下:

(1)该图有N个点,N-1条边。

(2)任意两点是可达的。

Input

第一行是一个整数N代表节点的个数。

接下来N-1行每行有两个整数U, V(1 ≤ U, V ≤ N),表示双向边(U, V)

Output

输出把树转化为环的最小消耗值。

Sample Input

4
1 2
2 3
2 4

Sample Output

3

Data Constraint

对于20%的数据,有1≤N≤10。

对于100%的数据,有1≤N≤1000000。

分析

早上写的时候想的是奇怪的DP

然后搞了一阵子发现可以贪心?

只有一个儿子的节点则保留不变,值上传

两个儿子的节点可以断开与父亲的联系,将子树中所有点连成一条链的代价和断开再连接的代价加入答案

三及以上个儿子的节点可以通过断开若干个儿子的关系转变成两个儿子的状态

这里默认树根是某条链的一端,所以如果树根属于后两种状态时,无需加上断开和连接的代价

最后不要忘了加连接链两端的代价1

#include <iostream>
#include <cstdio>
using namespace std;
const int N=1e6+10;
struct Graph {
    int v,nx;
}g[2*N];
int cnt,list[N];
int n,ans;
int f[N];
int stk[N][3],top;
bool b[N];

void Add(int u,int v) {
    g[++cnt]=(Graph){v,list[u]};list[u]=cnt;
    g[++cnt]=(Graph){u,list[v]};list[v]=cnt;
}

void DFS() {
    stk[++top][0]=1;stk[top][1]=0;stk[top][2]=0;
    while (top) {
        int u=stk[top][0];
        if (!list[u]) {
            if (stk[top][2]>=2) ans+=f[u]+(stk[top][1]!=0?2:0);
            b[u]=stk[top][2]<2;
            top--;
            u=stk[top][0];
            if (b[g[list[u]].v]) {
                stk[top][2]++;
                f[u]+=f[g[list[u]].v];
                if (stk[top][2]>2) f[u]+=2;
            }
            list[u]=g[list[u]].nx;
        }
        for (int i=list[u];i;i=list[u]=g[i].nx)
            if (g[i].v!=stk[top][1]) {
                stk[++top][0]=g[i].v,stk[top][1]=u,stk[top][2]=0;
                break;
            }
    }
}

int main() {
    scanf("%d",&n);
    for (int i=1,u,v;i<n;i++) scanf("%d%d",&u,&v),Add(u,v);
    DFS();
    printf("%d",ans+1);
}

原文地址:https://www.cnblogs.com/mastervan/p/11107782.html

时间: 2024-10-28 10:51:44

[贪心]JZOJ 3230 【佛山市选2013】树环转换的相关文章

BZOJ 2466: [中山市选2009]树( 高斯消元 )

高斯消元解异或方程组...然后对自由元进行暴搜.树形dp应该也是可以的... -------------------------------------------------------------------------------------- #include<cstdio> #include<cstring> #include<algorithm> #include<bitset> using namespace std; const int ma

bzoj2466: [中山市选2009]树

同上一题.(应该可以树形dp,然而我不会... #include<cstdio> #include<cstring> #include<iostream> #include<bitset> #include<algorithm> using namespace std; #define REP(i,s,t) for(int i=s;i<=t;i++) #define dwn(i,s,t) for(int i=s;i>=t;i--) #

【BZOJ2466】[中山市选2009]树 树形DP

[BZOJ2466][中山市选2009]树 Description 图论中的树为一个无环的无向图.给定一棵树,每个节点有一盏指示灯和一个按钮.如果节点的按扭被按了,那么该节点的灯会从熄灭变为点亮(当按之前是熄灭的),或者从点亮到熄灭(当按之前是点亮的).并且该节点的直接邻居也发生同样的变化. 开始的时候,所有的指示灯都是熄灭的.请编程计算最少要按多少次按钮,才能让所有节点的指示灯变为点亮状态. Input 输入文件有多组数据. 输入第一行包含一个整数n,表示树的节点数目.每个节点的编号从1到n.

数据结构(四)树---树的转换

(一)树转二叉树 步骤 1.加线:在所有兄弟结点之间加一条连线 2.去线:对树中每个结点,只保留他与第一个长子结点的连线,删除他与其他孩子结点之间的连线 3.层次调整.以树的根节点为轴心,将整棵树顺时针旋转一定角度,使结构层次分明. 注意:第一个孩子是二叉树结点的左孩子,兄弟转换过来的孩子是结点的右孩子 转换后,根节点只有左子树,最左侧链表不改变 (二)森林转二叉树 步骤 1.将每个树转换为二叉树 2.第一棵二叉树不动,从第二棵二叉树开始,依次吧后一棵二叉树的根节点作为前一棵二叉树的根节点的右子

怎么把CAD 2013的图纸转换成CAD 2007的版本?

怎么把CAD 2013的图纸转换成CAD 2007的版本?需要将CAD图纸文件的版本进行相关的转换应该怎么样进行操作使用CAD转换器软件应该怎么样进行操作,将CAD图纸文件进行向低版本的转换,接下来小编就要来教大家的就是怎么把CAD 2013的图纸转换成CAD 2007的版本的全部操作步骤,希望能够帮助到你们,望采纳! 步骤一:首先要打开电脑,打开浏览器在搜索框中输入"迅捷CAD转换器"去到迅捷CAD官网上然后点击下载然后进行安装! 步骤二:点击将安装的软件打开,进入软件选择CAD版本

2466: [中山市选2009]树

Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1416  Solved: 614[Submit][Status][Discuss] Description 图论中的树为一个无环的无向图.给定一棵树,每个节点有一盏指示灯和一个按钮.如果节点的按扭被按了,那么该节点的灯会从熄灭变为点亮(当按之前是熄灭的),或者从点亮到熄灭(当按之前是点亮的).并且该节点的直接邻居也发生同样的变化. 开始的时候,所有的指示灯都是熄灭的.请编程计算最少要按多少次按钮,才

HDU 6203 ping ping ping [LCA,贪心,DFS序,BIT(树状数组)]

题目链接:[http://acm.hdu.edu.cn/showproblem.php?pid=6203] 题意 :给出一棵树,如果(a,b)路径上有坏点,那么(a,b)之间不联通,给出一些不联通的点对,然后判断最少有多少个坏点. 题解 :求每个点对的LCA,然后根据LCA的深度排序.从LCA最深的点对开始,如果a或者b点已经有点被标记了,那么continue,否者标记(a,b)LCA的子树每个顶点加1. #include<Bits/stdc++.h> using namespace std;

BZOJ 4896 :[Thu Summer Camp2016]补退选 Trie树+Vector

4896: [Thu Summer Camp2016]补退选 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 315  Solved: 97[Submit][Status][Discuss] Description X是T大的一名老师,每年他都要教授许多学生基础的C++知识.在T大,每个学生在每学期的开学前都需要选课,每 次选课一共分为三个阶段:预选,正选,补退选:其中"补退选"阶段最忙碌.在补退选阶段,学生即可以选课,也 可以退课.对于

BZOJ 2466 [中山市选2009]树(高斯消元)

[题目链接] http://www.lydsy.com/JudgeOnline/problem.php?id=2466 [题目大意] 给定一棵树,每个节点有一盏指示灯和一个按钮.如果节点的按扭被按了, 那么该节点的灯会从熄灭变为点亮(当按之前是熄灭的),或者从点亮到熄灭 并且该节点的直接邻居也发生同样的变化.开始的时候,所有的指示灯都是熄灭的. 请编程计算最少要按多少次按钮,才能让所有节点的指示灯变为点亮状态. [题解] 高斯消元枚举自由变元回代. [代码] #include <cstdio>