[CSAcademy]Cycle Tree

题目大意:

定义环树是一张无向连通的简单图,它的生成方式如下:

  1. \(2\)个点\(1\)条边的图是环树;
  2. 对任意一个环树,加入\(k\)个点\(a_{1\sim k}\),加入方式为从原图中选择一条边\((u,v)\),连接\((u,a_1),(a_1,a_2)\ldots(a_{k-1},a_k),(a_k,v)\),得到的图也是环树。

给定一个\(n(n\le5\times10^4)\)个点,\(m(m\le10^5)\)条边的环树,求最大独立集大小。

思路:

每次选取一个度数为\(2\)的点,将这条边删掉,将相邻的两点间连上虚点。不断进行这样的操作,最后只会剩下\(2\)个点。

\(f[0/1][0/1][i][j]\)表示对于边\((i,j)\),是否选取\(i/j\)的最大独立集,按照删点的顺序进行DP即可。

每个点最多被删一次,因此时间复杂度\(\mathcal O(n+m)\)。

源代码:

#include<map>
#include<set>
#include<queue>
#include<cstdio>
#include<cctype>
#include<climits>
inline int getint() {
register char ch;
while(!isdigit(ch=getchar()));
register int x=ch^'0';
while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
return x;
}
const int N=5e4+1;
bool inq[N];
std::queue<int> q;
std::set<int> e[N],set[N];
std::map<int,int> f[2][2][N];
inline void add_edge(const int &u,const int &v) {
e[u].emplace(v);
e[v].emplace(u);
}
inline void add(int &x,const int &y) {
x+=y;
}
inline void up(int &x,const int &y) {
x=std::max(x,y);
}
int main() {
const int n=getint(),m=getint();
for(register int i=0;i<m;i++) {
const int u=getint(),v=getint();
add_edge(u,v);
f[0][0][u][v]=f[0][0][v][u]=0;
f[0][1][u][v]=f[1][0][v][u]=1;
f[1][0][u][v]=f[0][1][v][u]=1;
f[1][1][u][v]=f[1][1][v][u]=INT_MIN;
set[u].insert(v);
set[v].insert(u);
}
int ans=1;
for(register int i=1;i<=n;i++) {
if(e[i].size()==2) {
q.push(i);
inq[i]=true;
}
}
while(!q.empty()) {
const int x=q.front();
q.pop();
if(e[x].size()!=2) continue;
const int u=*e[x].begin(),v=*e[x].rbegin();
add(f[0][0][u][v],std::max(f[0][0][x][u]+f[0][0][x][v],f[1][0][x][u]+f[1][0][x][v]-1));
add(f[0][1][u][v],std::max(f[0][0][x][u]+f[0][1][x][v],f[1][0][x][u]+f[1][1][x][v]-1)-!!f[0][1][u][v]);
add(f[1][0][u][v],std::max(f[0][1][x][u]+f[0][0][x][v],f[1][1][x][u]+f[1][0][x][v]-1)-!!f[1][0][u][v]);
if(!set[u].count(v)) add(f[1][1][u][v],std::max(f[0][1][x][u]+f[0][1][x][v],f[1][1][x][u]+f[1][1][x][v]-1)-2*!!f[1][1][u][v]);
up(ans,f[0][0][v][u]=f[0][0][u][v]);
up(ans,f[1][0][v][u]=f[0][1][u][v]);
up(ans,f[0][1][v][u]=f[1][0][u][v]);
up(ans,f[1][1][v][u]=f[1][1][u][v]);
e[x].clear();
e[u].erase(x);
e[v].erase(x);
e[u].insert(v);
e[v].insert(u);
if(e[u].size()==2&&!inq[u]) {
q.push(u);
inq[u]=true;
}
if(e[v].size()==2&&!inq[v]) {
q.push(v);
inq[v]=true;
}
}
printf("%d\n",ans);
return 0;
}

[CSAcademy]Cycle Tree的更多相关文章

  1. [CSAcademy]Connected Tree Subgraphs

    题目大意: 给你一棵n个结点的树,求有多少种染色方案,使得染色过程中染过色的结点始终连成一块. 思路: 树形DP. 设f[x]表示先放x时,x的子树中的染色方案数,y为x的子结点. 则f[x]=pro ...

  2. 4105: [Thu Summer Camp 2015]平方运算

    首先嘛这道题目只要知道一个东西就很容易了:所有循环的最小公约数<=60,成一条链的长度最大为11,那么我们就可以用一个很裸的方法.对于在链上的数,我们修改直接暴力找出并修改.对于在环上的数,我们 ...

  3. Leetcode: Graph Valid Tree && Summary: Detect cycle in undirected graph

    Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), ...

  4. [CSAcademy]Find the Tree

    [CSAcademy]Find the Tree 题目大意: 交互题. 有一棵\(n(n\le2000)\)个结点的树,但是你并不知道树的形态.你可以调用\({\rm query}(x,y,z)\)( ...

  5. [CSAcademy]Virus on a Tree

    [CSAcademy]Virus on a Tree 题目大意: 给你一棵\(n(n\le10^5)\)个点的树,一开始点\(1\)有病毒,可以沿着边扩散.你可以事先切掉若干条边,使得病毒扩散不超过\ ...

  6. Terminating app due to uncaught exception 'CALayerInvalid', reason: 'layer <CALayer: 0x7fda42c66e30> is a part of cycle in its layer tree'

    iOS App里面所有的View构成一个组件树,这个树里面如果有了闭环就会出现这个报错,最常见的你不小在某UIViewController里面写了这样的代码: someView.addSubView( ...

  7. [LeetCode] Convert Sorted List to Binary Search Tree 将有序链表转为二叉搜索树

    Given a singly linked list where elements are sorted in ascending order, convert it to a height bala ...

  8. 学习RxJS:Cycle.js

    原文地址:http://www.moye.me/2016/06/16/learning_rxjs_part_two_cycle-js/ 是什么 Cycle.js 是一个极简的JavaScript框架( ...

  9. Graph Valid Tree

    Given n nodes labeled from 0 to n - 1 and a list of undirected edges (each edge is a pair of nodes), ...

随机推荐

  1. Libheap:一款用于分析Glibc堆结构的GDB调试工具

    Libheap是一个用于在Linux平台上分析glibc堆结构的GDB调试脚本,使用Python语言编写.         安装 Glibc安装 尽管Libheap不要求glibc使用GDB调试支持和 ...

  2. go 函数的作用域及可见性

    1.全局变量,在程序整个生命周期有效 比如: test.go 中 我们定义 了 a 作为全局变量,那么在这个程序中任何地方都可以调用a, 这个 2. 局部变量,分为两种:1)函数内定义,2)语句块内定 ...

  3. go 函数介绍

    1. 定义:有输入.有输出,用来执行一个指定任务的代码块 func functionname([parametername type]) [returntype] { //function body ...

  4. Shell脚本中字符串判空:使用-z 字符串长度为0时,为真,-n字符串长度不为0,为真。这两个都不靠谱【转】

    最近发现使用  -z   和  -n  来判断字符串判空,或不空时,很不靠谱. 使用下面的方法最可靠: if [ "x${value}" == "x" ]    ...

  5. python socket编程和黏包问题

    一.基于TCP的socket tcp是基于链接的,必须先启动服务端,然后再启动客户端去链接服务端,有顺序,不重复,可靠.不会被加上数据边界. server端 import socket sk = so ...

  6. JavaBean的实用工具Lombok(省去get、set等方法)

    转:https://blog.csdn.net/ghsau/article/details/52334762 背景   我们在开发过程中,通常都会定义大量的JavaBean,然后通过IDE去生成其属性 ...

  7. 树莓派指定静态IP

    1.备份并清空 interfaces 文件 cp /etc/network/interfaces /etc/network/interfaces.bak vi /etc/network/interfa ...

  8. TImage 显示 资源中 的图片、TResourceStream、资源文件

    unit Unit5; interface uses Winapi.Windows, Winapi.Messages, System.SysUtils, System.Variants, System ...

  9. OA项目Spring.Net代替抽象工厂(三)

    Servrvice层的代码: <?xml version="1.0" encoding="utf-8" ?> <objects xmlns=& ...

  10. [水煮 ASP.NET Web API2 方法论](3-1)集中式路由

    问题 怎样集中的定义路由 解决方案 通过调用 HttpRouteCollectionExtension 类中的 MapHttpRoute 扩展方法在 HttpRouteCollection 中定义路由 ...