BZOJ4316: 小C的独立集

传送门

圆方树预备知识。

首先搞出DFS树,然后设状态$f[node][OK][OKanc]$为别表示在当前点选/不限和环顶节点选/不选。

剩下的就是TreeDP常规的东西。

P.S.课件上说第一个状态设为父亲的,亲测没有设成自己来得方便

//BZOJ 4316
//by Cydiater
//2017.2.12
#include <iostream>
#include <queue>
#include <map>
#include <ctime>
#include <cstdlib>
#include <cstdio>
#include <cstring>
#include <string>
#include <algorithm>
#include <iomanip>
#include <cmath>
#include <bitset>
#include <set>
#include <vector>
using namespace std;
#define ll long long
#define up(i,j,n)	for(int i=j;i<=n;i++)
#define down(i,j,n)	for(int i=j;i>=n;i--)
#define cmax(a,b)	a=max(a,b)
#define cmin(a,b)	a=min(a,b)
#define Auto(i,node)	for(int i=LINK[node];i;i=e[i].next)
const int MAXN=2e5+5;
const int oo=0x3f3f3f3f;
inline int read(){
	char ch=getchar();int x=0,f=1;
	while(ch>‘9‘||ch<‘0‘){if(ch==‘-‘)f=-1;ch=getchar();}
	while(ch>=‘0‘&&ch<=‘9‘){x=x*10+ch-‘0‘;ch=getchar();}
	return x*f;
}
int LINK[MAXN],N,M,len=0,fa[MAXN],dep[MAXN],anc[MAXN],f[MAXN][2][2],fat[MAXN];
bool istop[MAXN];
struct edge{
	int y,next;
}e[MAXN];
namespace solution{
	inline void insert(int x,int y){e[++len].next=LINK[x];LINK[x]=len;e[len].y=y;}
	inline void Insert(int x,int y){insert(x,y);insert(y,x);}
	void DFS(int node,int father,int deep){
		dep[node]=deep+1;fa[node]=father;
		Auto(i,node)if(e[i].y!=father&&!dep[e[i].y])
			DFS(e[i].y,node,deep+1);
	}
	void Prepare(){
		N=read();M=read();
		up(i,1,M){
			int x=read(),y=read();
			Insert(x,y);
		}
		DFS(1,0,0);
		up(node,1,N)Auto(i,node){
			if(dep[e[i].y]<dep[node]&&e[i].y!=fa[node]){
				istop[e[i].y]=1;
				anc[node]=e[i].y;
				int tmp=node;
				while(tmp!=e[i].y){
					fat[tmp]=e[i].y;
					tmp=fa[tmp];
				}
			}
		}
	}
	int TreeDP(int node,int OK,int OKanc){
		if(f[node][OK][OKanc]!=-1)return f[node][OK][OKanc];
		f[node][OK][OKanc]=0;
		if(OK){
			if(anc[node]&&OKanc)return f[node][OK][OKanc];
			Auto(i,node)if(dep[e[i].y]==dep[node]+1){
				if(fat[e[i].y]==node&&istop[node])
					f[node][OK][OKanc]+=TreeDP(e[i].y,0,1);
				else f[node][OK][OKanc]+=TreeDP(e[i].y,0,OKanc);
			}
			f[node][OK][OKanc]++;
		}else{
			Auto(i,node)if(dep[e[i].y]==dep[node]+1){
				if(fat[e[i].y]==node&&istop[node]){
					f[node][OK][OKanc]+=max(TreeDP(e[i].y,0,0),TreeDP(e[i].y,1,0));
				}
				else f[node][OK][OKanc]+=max(TreeDP(e[i].y,0,OKanc),TreeDP(e[i].y,1,OKanc));
			}
		}
		return f[node][OK][OKanc];
	}
}
int main(){
	//freopen("input.in","r",stdin);
	using namespace solution;
	Prepare();
	memset(f,-1,sizeof(f));
	cout<<max(TreeDP(1,1,1),TreeDP(1,0,0))<<endl;
	return 0;
}
时间: 2024-08-23 23:21:03

BZOJ4316: 小C的独立集的相关文章

BZOJ4316 小C的独立集 【仙人掌】

题目 图论小王子小C经常虐菜,特别是在图论方面,经常把小D虐得很惨很惨. 这不,小C让小D去求一个无向图的最大独立集,通俗地讲就是:在无向图中选出若干个点,这些点互相没有边连接,并使取出的点尽量多. 小D虽然图论很弱,但是也知道无向图最大独立集是npc,但是小C很仁慈的给了一个很有特点的图: 图中任何一条边属于且仅属于一个简单环,图中没有重边和自环.小C说这样就会比较水了. 小D觉得这个题目很有趣,就交给你了,相信你一定可以解出来的. 输入格式 第一行,两个数n, m,表示图的点数和边数. 第二

【题解】Bzoj4316小C的独立集

决定要开始学习圆方树 & 仙人掌相关姿势.加油~~ 其实感觉仙人掌本质上还是一棵树,长得也还挺优美的.很多的想法都可以往树的方面上靠,再针对仙人掌的特性做出改进.这题首先如果是在树上的话那么实际上就是没有上司的舞会.当出现了环的时候意味着我们需要针对环的存在做出特殊的处理. 还是设立状态 \(f[i][1/0]\) 表示在 \(i\) 的子树内(包括\(i\))时选取 \(i\) 与不选取 \(i\) 的最大独立集大小.当转移发生在树边上的时候,直接转移.当不是树边的时候,我们可以将环上的点单独

【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很仁慈的给了一个很

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

4316: 小C的独立集 Time Limit: 10 Sec  Memory Limit: 128 MB Description 图论小王子小C经常虐菜,特别是在图论方面,经常把小D虐得很惨很惨. 这不,小C让小D去求一个无向图的最大独立集,通俗地讲就是:在无向图中选出若干个点,这些点互相没有边连接,并使取出的点尽量多. 小D虽然图论很弱,但是也知道无向图最大独立集是npc,但是小C很仁慈的给了一个很有特点的图: 图中任何一条边属于且仅属于一个简单环,图中没有重边和自环.小C说这样就会比较水了

比拼生态和未来,Spark和Flink哪家强?

概 况 Spark 是最活跃的 Apache 项目之一.从 2014 年左右开始得到广泛关注.Spark 的开源社区一度达到上千的活跃贡献者.最主要推动者是 Databricks,由最初的 Spark 创造者们成立的公司.今年 6 月的 Spark+AI 峰会参加人数超过 4000. Spark 因为在引擎方面比 MapReduce 全面占优,经过几年发展和 Hadoop 生态结合较好,已经被广泛视为 Hadoop MapReduce 引擎的取代者.Flink 也是 Apache 顶级项目,创始

hdu 1569 方格取数(2) 网络流 最大点权独立集

方格取数(2) Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5146    Accepted Submission(s): 1610 Problem Description 给你一个m*n的格子的棋盘,每个格子里面有一个非负数. 从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的

hdu 4859 最大点权独立集的变形(方格取数的变形)

/*刚开始不会写,最大点权独立集神马都不知道,在潘神的指导下终于做出来,灰常感谢ps: 和方格取数差不多奇偶建图,对于D必割点权为0,对于.必然不割点权为inf.然后和方格取数差不多的建图 .--.||E权值为2,,.||E--D权值为0. 最大点权独立集=sum-最小点权覆盖. */ #include<stdio.h> #include<string.h> #include<queue> using namespace std; #define inf 0x3ffff

hdu 1565 最大点权独立集

题意:给你一个m*n的格子的棋盘,每个格子里面有一个非负数.从中取出若干个数,使得任意的两个数所在的格子没有公共边,就是说所取数所在的2个格子不能相邻,并且取出的数的和最大. 链接:点我 分析转自:点我    二分图最小点覆盖和最大独立集都可以转化为最大匹配求解.在这个基础上,把每个点赋予一个非负的权值,这两个问题就转化为:二分图最小点权覆盖和二分图最大点权独立集. 二分图最小点权覆盖 从x或者y集合中选取一些点,使这些点覆盖所有的边,并且选出来的点的权值尽可能小. 建模: 原二分图中的边(u,

【BZOJ-1952】Area [坑题] 仙人掌DP + 最大点权独立集(改)

1952: [Sdoi2010]Area Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 73  Solved: 23[Submit][Status][Discuss] Description 小猪iPig来到了一个叫做pigsty的城市里,pigsty是一座专门为小猪所准备的城市,城市里面一共有n个小区给小猪们居住,并且存在许多条无向边连接着许多小区.因为这里是一个和谐的城市,所以小猪iPig准备在这个城市里面度过他的余生.若干年之后小猪iPig