http://uoj.ac/problem/168

没想到是网络流

官方题解地址

http://jiry-2.blog.uoj.ac/blog/1115

subtask2告诉我们度数为012的点对答案无影响

subtask3告诉我们原图\(|E| > 2|V| - 2\)时不是丛林的

证明一个结论

若对于原图所有的子图都满足\(|E| \le 2|V| - 2\)则是一个丛林

对子图大小施归纳法

\(n = 1\)是丛林

当\(n \geq 2\)时

设当前图度数最小的节点为\(u\)

仅讨论\(du[u] = 3\)的情况(0, 1, 2同subtask2)

记\(|E| = 2|V| - 2\)的子图为Dark图

Dark 交 Dark 得到的图也是Dark

证明的话考虑总的减去交的 每一部分都是满足的

然后设\(u\)在原图和\(a, b, c\)有边

在原图必不存在包含\(a, b, c\)的Dark子图(反证法)

然后就可以科学的构造\(n\)的时候的丛林了

如果有一个Dark子图包含\(a,b\)不包含\(c\)

那么一颗树选择\(u->a, u->b\)另一棵树选择\(u->c\)

然后就是问是否存在一个非空子图

满足\(|E| > 2|V| - 2\)

相当于点权值为\(-2\)边权值为\(1\)

这是一个最大权闭合子图的模型

但是是非空的

那么就枚举必选哪一个点

把这个点权值设成\(0\)跑网络流就好了

复杂度是\(\mathcal O(nm\sqrt n)\)的

观察到每一次枚举一个点只会改变一条边和他的反向边流量

所以退流就好了

学了一下退流的姿势

比如说要退边\(<u, v>\)的流

只需要\(t->v\)和\(u->s\)分别跑最大流就好了

感性YY一下

可能讲的好乱 看官方题解吧

还要卡常数qwq

#include <bits/stdc++.h>
#define rint register int
#define fo(i, n) for(int i = 1; i <= (n); i ++)
#define out(x) cerr << #x << " = " << x << "\n"
#define type(x) __typeof((x).begin())
#define foreach(it, x) for(type(x) it = (x).begin(); it != (x).end(); ++ it)
using namespace std;
// by piano
template<typename tp> inline void read(tp &x) {
x = 0;char c = getchar(); bool f = 0;
for(; c < '0' || c > '9'; f |= (c == '-'), c = getchar());
for(; c >= '0' && c <= '9'; x = (x << 3) + (x << 1) + c - '0', c = getchar());
if(f) x = -x;
}
namespace mf {
static const int N = 8888;
static const int M = 23333;
static const int inf = 1e9;
struct E {
int nxt, to, fl;
}e[M << 1];
int d[N], head[N], cur[N], e_cnt = 1;
int n, s, t;
inline void init(int _n, int _s, int _t) {
n = _n; e_cnt = 1;
fill(head, head + n + 1, 0);
}
inline void add(int u, int v, int fl) {
e[++ e_cnt] = (E) {head[u], v, fl}; head[u] = e_cnt;
}
inline void link(int u, int v, int fl) {
add(u, v, fl); add(v, u, 0);
}
inline bool bfs(void) {
queue<int> q;
fill(d, d + n + 1, -1);
d[s] = 0; q.push(s);
while(!q.empty()) {
int u = q.front(); q.pop();
for(rint i = head[u]; i; i = e[i].nxt) if(e[i].fl) {
int v = e[i].to;
if(!~ d[v]) {
d[v] = d[u] + 1, q.push(v);
if(v == t) return true;
}
}
}
return d[t] != -1;
}
inline int dfs(int u, int f) {
if(u == t || !f) return f;
rint used = 0, t;
for(rint &i = cur[u]; i; i = e[i].nxt) if(e[i].fl) {
int v = e[i].to;
if(d[v] != d[u] + 1) continue;
t = dfs(v, min(f - used, e[i].fl));
used += t; e[i].fl -= t; e[i ^ 1].fl += t;
if(used == f) break;
}
if(!used) d[u] = -1;
return used;
}
inline int doit(int _s, int _t, int f) {
int fl = 0; s = _s; t = _t;
while(bfs() && fl < f) {
memcpy(cur, head, sizeof (int) * (n + 2));
fl += dfs(s, f - fl);
}
return fl;
}
} const int inf = 1e9;
int n, m, s, t;
#define GG return puts("No"), 0;
main(void) {
read(n); read(m);
s = n + m + 1; t = s + 1;
mf::init(t, s, t);
for(rint i = 1; i <= n; i ++) {
mf::link(i, t, 2);
}
for(rint i = 1; i <= m; i ++) {
mf::link(s, i + n, 1);
}
for(rint i = 1; i <= m; i ++) {
int x, y; read(x); read(y);
mf::link(i + n, x, inf);
mf::link(i + n, y, inf);
}
int fl = mf::doit(s, t, inf);
if(m - fl > 0) GG;
for(rint i = 1; i <= n; i ++) {
fl -= mf::doit(i, s, mf::e[i * 2 + 1].fl);
mf::e[i * 2].fl = mf::e[i * 2 + 1].fl = 0;
fl += mf::doit(s, t, inf);
if(m - fl > 0) GG;
mf::e[i * 2].fl = 2;
}
cout << "Yes\n";
}

网路流 uoj 168 元旦老人与丛林的更多相关文章

  1. 2018.07.28 uoj#169. 【UR #11】元旦老人与数列(线段树)

    传送门 线段树好题. 维护区间加,区间取最大值,维护区间最小值,历史区间最小值. 同样先考虑不用维护历史区间最小值的情况,这个可以参考这道题的解法,维护区间最小和次小值可以解决前两个操作,然后使用历史 ...

  2. 【UOJ#169】元旦老人与数列

    论文题. 考虑到这题的维护和区间操作是反向的,也就是说无法像V那题快速的合并标记. 我们知道,一个区间的最小值和其他值是可以分开来维护的,因为如果一个区间被整体覆盖,那么最小值始终是最小值. 对于被覆 ...

  3. [UOJ #167]【UR #11】元旦老人与汉诺塔

    题目大意:给你一个有$n$个盘子的汉诺塔状态$S$,问有多少种不同的操作方法,使得可以在$m$步以内到达状态$T$.$n,m\leqslant100$ 题解:首先可以知道的是,一个状态最多可以转移到其 ...

  4. UOJ 52 元旦激光炮

    http://uoj.ac/problem/52 题意:每次可以得到3个序列中 思路:每次分别取出三个序列的K/3长度的位置,取最小的那个,然后每次减掉它,总复杂度是Nlog3N #include & ...

  5. UR11 A.元旦老人与汉诺塔

    题目:http://uoj.ac/contest/23/problem/167 如果我们拿个map来存状态的话.设当前状态是v,下一个状态是s.有f[i+1][s]+=f[i][v]. 初始f[0][ ...

  6. uoj169:元旦老人与数列

    题意:http://uoj.ac/problem/169 sol  :线段树..........蜜汁TLE了一个点,不管了..... 代码抄snowMyDream的,orz........... 线段 ...

  7. uoj167 元旦老人与汉诺塔(记忆化搜索)

    QwQ太懒了,题目直接复制uoj的了 QwQ这个题可以说是十分玄学的一道题了 首先可以暴搜,就是\(dfs\)然后模拟每个过程是哪个柱子向哪个柱子移动 不多解释了,不过实现起来还是有一点点难度的 直接 ...

  8. UOJ169. 【UR #11】元旦老人与数列

    传送门 考虑用 \(segment~tree~beats\) 那一套理论,维护区间最小值 \(mn\) 和严格次小值 \(se\) 那么可以直接 \(mlog^2n\) 维护前三个操作 考虑维护历史最 ...

  9. 【bzoj3894】文理分科 网路流

    [bzoj3894]文理分科 2015年3月25日3,4002 Description  文理分科是一件很纠结的事情!(虽然看到这个题目的人肯定都没有纠 结过)  小P所在的班级要进行文理分科.他的班 ...

随机推荐

  1. Atcoder Grand Contest 036 D - Negative Cycle

    Atcoder Grand Contest 036 D - Negative Cycle 解题思路 在某些情况下,给一张图加或删一些边要使图合法的题目要考虑到最短路的差分约束系统.这一题看似和最短路没 ...

  2. Spring Cloud Alibaba学习笔记(21) - Spring Cloud Gateway 自定义全局过滤器

    在前文中,我们介绍了Spring Cloud Gateway内置了一系列的全局过滤器,本文介绍如何自定义全局过滤器. 自定义全局过滤需要实现GlobalFilter 接口,该接口和 GatewayFi ...

  3. HDFS-HA高可用集群搭建

    HA高可用集群搭建 1.总体集群规划 在hadoop102.hadoop103和hadoop104三个节点上部署Zookeeper. hadoop102 hadoop103 hadoop104 Nam ...

  4. 在本地库不连接远远程库的情况下操作远程库-----sql server

    --创建链接服务器 --前面都是固定不变的------q:自己随便起-----38.107.111.185:远程服务器的ip exec sp_addlinkedserver 'q', ' ', 'SQ ...

  5. C# vb .net实现亮度调整特效滤镜效果

    在.net中,如何简单快捷地实现Photoshop滤镜组中的亮度调整呢?答案是调用SharpImage!专业图像特效滤镜和合成类库.下面开始演示关键代码,您也可以在文末下载全部源码: 设置授权 第一步 ...

  6. IOS - UDID IDFA IDFV MAC keychain

    在开发过程中,我们经常会被要求获取每个设备的唯一标示,以便后台做相应的处理.我们来看看有哪些方法来获取设备的唯一标示,然后再分析下这些方法的利弊. 具体可以分为如下几种: UDID IDFA IDFV ...

  7. ColdFusion 编写WebService 示例

    1.开发 Web Services,编写cfcdemo.cfc组件,代码如下: <cfcomponent style ="document" namespace = &quo ...

  8. 1+X证书学习日志——函数

    工具得特点: 1:重复性使用 2:隐藏内部原理(细节) 3:选择性应用 创建函数: 1:关键字 function 函数名称(){ } 2:字面量创建 var fn = function(){ } 3: ...

  9. mysql如何让有数据的表的自增主键重新设置从1开始连续自增

    项目开发中,有些固定数据在数据表中,主键是从1自增的,有时候我们会删除一些数据, 这种情况下,主键就会不连续.如何恢复到像第一次插入数据一样主键从1开始连续增长, 这里我找到一种解决方法: 如上面一张 ...

  10. redhat6.7环境下oracle11gR2 RAC静默安装

    (一)基础环境 虚拟机环境 :vmware workstation 12 操作系统    : redhat6.7 - 64bit 数据库版本 :11.2.0.4 (二)安装前的环境准备 (2.1)配置 ...