BZOJ 4316: 小C的独立集 仙人掌 + 树形DP

4316: 小C的独立集

Time Limit: 10 Sec  Memory Limit: 128 MB

Description

图论小王子小C经常虐菜,特别是在图论方面,经常把小D虐得很惨很惨。

这不,小C让小D去求一个无向图的最大独立集,通俗地讲就是:在无向图中选出若干个点,这些点互相没有边连接,并使取出的点尽量多。

小D虽然图论很弱,但是也知道无向图最大独立集是npc,但是小C很仁慈的给了一个很有特点的图: 图中任何一条边属于且仅属于一个简单环,图中没有重边和自环。小C说这样就会比较水了。

小D觉得这个题目很有趣,就交给你了,相信你一定可以解出来的。

Input

第一行,两个数n, m,表示图的点数和边数。

第二~m+1行,每行两个数x,y,表示x与y之间有一条无向边。

Output

输出这个图的最大独立集。

Sample Input

5 6
1 2
2 3
3 1
3 4
4 5
3 5

Sample Output

2

HINT

100% n <=50000, m<=60000

Source

题解:

   这个图是仙人掌图啊

  对于一个环就直接 另外 DP就好了

  环与环相邻,逐个求解不受影响啊

  设定dp[i][0/1] 表示当前i为根节点的且选与不选的状态下 其子树 的 最大可选节点数

#include <bits/stdc++.h>
inline long long read(){long long x=0,f=1;char ch=getchar();while(ch<‘0‘||ch>‘9‘){if(ch==‘-‘)f=-1;ch=getchar();}while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}return x*f;}
using namespace std;
#define ls i<<1
#define rs ls | 1
#define mid ((ll+rr)>>1)
#define MP make_pair
typedef long long LL;
typedef unsigned long long ULL;
const long long INF = 1e18+1LL;
const double pi = acos(-1.0);
const int N = 2e5 + 10, M = 502, inf = 1e9;

vector<int > G[N];
int dp[N][2],n,m,fa[N];
int dep[N];

void gao(int x,int y) {
    //cout<<x<<" " <<y<<endl;
    int last0 = 0, last1 = 0;
    for(int i = x; i != y; i = fa[i]) {
        int tmp = last0;
        last0 = max(last0,last1) + dp[i][0];
        last1 = tmp + dp[i][1];
    }
    dp[y][0] += max(last1,last0);

   // int fuck =  max(last0,last1);
    last0 = -inf, last1 = 0;
    for(int i = x; i != y; i = fa[i]) {
        int tmp = last0;
        last0 = max(last0,last1) + dp[i][0];
        last1 = tmp + dp[i][1];
    }

   // fuck = max(max(last0,last1),fuck);

    //dp[y][0] += fuck;
    dp[y][1] += last0;
}

void dfs(int u,int f) {
    dep[u] = dep[f] + 1;
    fa[u] = f;
    dp[u][1] = 1;
  //  cout<<u<<" "<<f<<endl;
    for(int i = 0; i < G[u].size(); ++i) {
        int to = G[u][i];
        if(to == f) continue;
        if(!dep[to]) {dfs(to,u);}
    }
    for(int i = 0; i < G[u].size(); ++i) {
        int to = G[u][i];
        if(to == f) continue;
        if(dep[to] > dep[u] && fa[to] != u) {///montherfuck
            gao(to,u);
        }
    }
}

int main() {
    scanf("%d%d",&n,&m);
    for(int i = 1; i <= m; ++i) {
        int u,v;
        scanf("%d%d",&u,&v);
        G[u].push_back(v);
        G[v].push_back(u);
    }
    dfs(1,0);
    printf("%d\n",max(dp[1][0],dp[1][1]));
    return 0;
}
/*
17 20
1 2
2 3
3 4
4 5
5 2
2 6
6 7
7 8
8 9
9 10
10 11
11 12
12 6
6 13
13 14
14 15
15 16
16 17
17 13
13 1
*/
时间: 2024-08-24 11:51:51

BZOJ 4316: 小C的独立集 仙人掌 + 树形DP的相关文章

【BZOJ-4316】小C的独立集 仙人掌DP + 最大独立集

4316: 小C的独立集 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 57  Solved: 41[Submit][Status][Discuss] Description 图论小王子小C经常虐菜,特别是在图论方面,经常把小D虐得很惨很惨. 这不,小C让小D去求一个无向图的最大独立集,通俗地讲就是:在无向图中选出若干个点,这些点互相没有边连接,并使取出的点尽量多. 小D虽然图论很弱,但是也知道无向图最大独立集是npc,但是小C很仁慈的给了一个很

#290. 【ZJOI2017】仙人掌(数数+仙人掌+树形dp)

传送门 模拟赛的时候打了个表发现为一条链的时候答案是\(2^{n-2}\)竟然顺便过了第一个点 然后之后订正的时候强联通分量打错了调了一个上午 首先不难发现我们可以去掉所有在环上的边,那么就变成了一个森林,不同的树之间不可能有连边,那么只要所有树的答案乘起来就好了,只要在每一棵树内部树形\(dp\)即可 考虑对于\(u\),它的子树如何统计答案 我们强制子树必须得向外连一条边(显然最多只有一条),然后往上统计 如果子树里没有向外连边,每一棵子树的答案乘起来 如果向外连边的话,那么要把子树内的边两

BZOJ 1040 ZJOI 2008 骑士 基环树林+树形DP

题目大意:有一些骑士,他们每个人都有一个权值.但是由于一些问题,每一个骑士都特别讨厌另一个骑士.所以不能把他们安排在一起.求这些骑士所组成的编队的最大权值和是多少. 思路:首先貌似是有向图的样子,但是一个人讨厌另一个人,他们两个就不能在一起,所以边可以看成是无向的. n个点,n条无向边,好像是一颗基环树.但其实这是一个基环树林,因为题中并没有说保证图一定联通. 然后就可以深搜了,处理出每一个联通块.其实每一个联通块就是一个基环树,在这个基环树上进行树形DP.求出最大值,然后累加到答案上.答案要开

[BZOJ 1017][JSOI2008]魔兽地图DotR(树形Dp)

Description DotR (Defense of the Robots) Allstars是一个风靡全球的魔兽地图,他的规则简单与同样流行的地图DotA (Defense of the Ancients) Allstars.DotR里面的英雄只有一个属性——力量.他们需要购买装备来提升自己的 力量值,每件装备都可以使佩戴它的英雄的力量值提高固定的点数,所以英雄的力量值等于它购买的所有装备的力 量值之和.装备分为基本装备和高级装备两种.基本装备可以直接从商店里面用金币购买,而高级装备需要用

BZOJ 2097 Exercise 奶牛健美操 二分答案+树形DP+贪心

题目大意:给定一棵树,可以删掉k条边,求删掉后森林中所有树直径的最大值的最小值 最大值最小,典型的二分答案 此题我们二分树的直径,每次二分DFS一次,对于每个节点统计出所有子树删边后的dis,排序,贪心删掉最大的,直到最大的两个子树相加不会超过二分的答案为止 时间复杂度O(nlog^2n) 老子的二分居然写挂了...桑不起啊啊啊啊 #include<cstdio> #include<cstring> #include<iostream> #include<algo

【BZOJ】2435: [Noi2011]道路修建(树形dp)

http://www.lydsy.com/JudgeOnline/problem.php?id=2435 我怎么感觉那么水.. 坑的是,dfs会爆...好吧..用bfs.. #include <cstdio> #include <cstring> #include <cmath> #include <string> #include <iostream> #include <algorithm> #include <queue&

BZOJ 3437 小P的牧场 斜率优化DP

题目大意:有些按照一字排列的牧场,每一个牧场有一个费用和放牧数量.现在要在一些牧场上建造控制站,目的是控制所有的牧场,建立控制站的基础费用就是每个牧场的费用,然后每一个牧场需要付这个牧场的放养数量*它与右边相邻的控制站的距离.求最小的费用. 思路:直接弄有些不好弄,需要两个前缀和来进行差分. sum[i] = Σsrc[i] _sum[i] = Σsrc[i]*i 然后DP方程就是f[i] = f[j] + (sum[i] - sum[j]) * i - _sum[i] + _sum[j] 简单

BZOJ 2159: Crash 的文明世界(树形dp+第二类斯特林数+组合数)

题意: 给定一棵 \(n\) 个点的树和一个常数 \(k\) , 对于每个 \(i\) , 求 \[\displaystyle S(i) = \sum _{j=1} ^ {n} \mathrm{dist}(i, j)^k\] \(n ≤ 50000, k ≤ 150\) 题解 : 先划划那个 \(S(i)\) 的式子 我们需要知道一个化 \(x^n(n \ge 0)\) 的东西qwq \[\displaystyle x^n=\sum_{k=0}^{n}\begin{Bmatrix} n \\ k

bzoj 2427: [HAOI2010]软件安装【tarjan+树形dp】

一眼最大权闭合子图,然后开始构图,画了画之后发现我其实是个智障网络流满足不了m,于是发现正确的打开方式应该是一眼树上dp 然后仔细看了看性质,发现把依赖关系建成图之后是个奇环森林,这个显然不能直接dp 发现这个环要选的话只能选整个环,所以tarjan缩一下点,然后再跑树上背包就行了 #include<iostream> #include<cstdio> #include<vector> #include<cstring> using namespace st