[luoguP1041] 传染病控制(DFS)

传送门

n <= 300

结果裸的dfs就直接过了。。

枚举每一层,枚举删除每一层的边,然后把删除的边所连接的子树全部删去

代码

#include <vector>
#include <cstdio>
#include <cstring>
#include <iostream>
#define N 301
#define min(x, y) ((x) < (y) ? (x) : (y))
#define max(x, y) ((x) > (y) ? (x) : (y))

int n, m, cnt, maxd, ans = ~(1 << 31);
int head[N], to[N << 1], next[N << 1], f[N], deep[N], size[N];
std::vector <int> vec[N];
bool vis[N];

inline int read()
{
	int x = 0, f = 1;
	char ch = getchar();
	for(; !isdigit(ch); ch = getchar()) if(ch == ‘-‘) f = -1;
	for(; isdigit(ch); ch = getchar()) x = (x << 1) + (x << 3) + ch - ‘0‘;
	return x * f;
}

inline void add(int x, int y)
{
	to[cnt] = y;
	next[cnt] = head[x];
	head[x] = cnt++;
}

inline void dfs(int u)
{
	int i, v;
	size[u] = 1;
	maxd = max(maxd, deep[u] = deep[f[u]] + 1);
	vec[deep[u]].push_back(u);
	for(i = head[u]; i ^ -1; i = next[i])
	{
		v = to[i];
		if(v ^ f[u])
		{
			f[v] = u;
			dfs(v);
			size[u] += size[v];
		}
	}
}

inline void dfs2(int u, int x)
{
	int i, v;
	vis[u] = x;
	for(i = head[u]; i ^ -1; i = next[i])
	{
		v = to[i];
		if(v ^ f[u]) dfs2(v, x);
	}
}

inline void dfs1(int k, int sum)
{
	ans = min(ans, n - sum);
	if(k == maxd + 1) return;
	int i, x;
	for(i = 0; i < vec[k].size(); i++)
	{
		x = vec[k][i];
		if(!vis[x])
		{
			dfs2(x, 1);
			dfs1(k + 1, sum + size[x]);
			dfs2(x, 0);
		}
	}
}

int main()
{
	int i, x, y;
	n = read();
	m = read();
	memset(head, -1, sizeof(head));
	for(i = 1; i <= m; i++)
	{
		x = read();
		y = read();
		add(x, y);
		add(y, x);
	}
	dfs(1);
	dfs1(2, 0);
	printf("%d\n", ans);
	return 0;
}

  

时间: 2024-10-29 19:07:05

[luoguP1041] 传染病控制(DFS)的相关文章

LuoguP1041 传染病控制

题目地址 题目链接 题解 这里讲一个非正解--贪心+随机化. 贪心的想法是什么? 我们dfs一遍处理出每个节点子树内的节点数量,记为\(siz\). 贪心的砍掉\(siz\)最大的那个子树,在树的形态比较正常的情况下是可以得到最优解的. 如何hack掉这种贪心? 构造一条链,在中间的地方放一个"很胖"的分支,可以只分两层,每层的节点构造多一些(注意要使这个分支的节点数量小于链下半部分的节点数量) 这样子我们按照上述贪心,将会得到错误的结果,更优的做法是把这个分支直接砍掉(因为链上每次传

洛谷 P1041 传染病控制

P1041 传染病控制 dfs枚举去掉的子树,更新当前感染节点 emmmm 这个题,每次去掉最大的子树的做法是错误的 比如 hhh,按照那个贪心的思路肯定是先去掉左边的子树,这样答案会是4 但是先去掉右边的子树的话答案就是3 1 #include<bits/stdc++.h> 2 using namespace std; 3 #define maxn 1000000+15 4 int n,m,x,y,fa[maxn],mmp[10000],sum[maxn],ans=1; 5 vector&l

P1041 传染病控制(dfs)

P1041 传染病控制 题目背景 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府决定不惜一切代价控制传染病的蔓延.不幸的是,由于人们尚未完全认识这种传染病,难以准确判别病毒携带者,更没有研制出疫苗以保护易感人群.于是,蓬莱国的疾病控制中心决定采取切断传播途径的方法控制疾病传播.经过 WHOWHO(世界卫生组织)以及全球各国科研部门的努力,这种新兴传染病的传播途径和控制方法已经研究清楚,剩下的任务就是由你协助蓬莱国疾控中心制定一个有效的控制办法. 题

NOIP2003传染病控制[按层DFS]

题目背景 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国大范围流行,该国政府决定不惜一切代价控制传染病的蔓延.不幸的是,由于人们尚未完全认识这种传染病,难以准确判别病毒携带者,更没有研制出疫苗以保护易感人群.于是,蓬莱国的疾病控制中心决定采取切断传播途径的方法控制疾病传播.经过 WHO(世界卫生组织)以及全球各国科研部门的努力,这种新兴传染病的传播途径和控制方法已经研究清楚,剩下的任务就是由你协助蓬莱国疾控中心制定一个有效的控制办法. 题目描述 研究表明,这种传染病的

NOIP2003 传染病控制

题四     传染病控制 [问题背景] 近来,一种新的传染病肆虐全球.蓬莱国也发现了零星感染者,为防止该病在蓬莱国 大范围流行,该国政府决定不惜一切代价控制传染病的蔓延.不幸的是,由于人们尚未完 全认识这种传染病,难以准确判别病毒携带者,更没有研制出疫苗以保护易感人群.于是, 蓬莱国的疾病控制中心决定采取切断传播途径的方法控制疾病传播.经过 WHO(世界卫 生组织)以及全球各国科研部门的努力,这种新兴传染病的传播途径和控制方法已经研究 消楚,剩下的任务就是由你协助蓬莱国疾控中心制定一个有效的控制

P1041 传染病控制——暴力遍历所有相同深度的节点

P1041 传染病控制 说实话这种暴力我还是头一次见,每次病毒都会往下传染一层: 数据范围小,我们可以直接枚举当前层保护谁就好了: 用vector 记录相同层数的节点:维护已经断了的点: 如果超出最底层或者都已经被保护就更新答案: #include<cstdio> #include<cstring> #include<vector> #include<algorithm> using namespace std; const int maxn=1010; v

解救小哈——DFS算法举例

一.问题引入 有一天,小哈一个人去玩迷宫.但是方向感不好的小哈很快就迷路了.小哼得知后便去解救无助的小哈.此时的小哼已经弄清楚了迷宫的地图,现在小哼要以最快的速度去解救小哈.那么,问题来了... 二.问题的分析 首先我们用一个二维数组来存储这个迷宫,刚开始的时候,小哼处于迷宫的入口处(1,1),小哈在(p,q).其实这道题的的本质就在于找从(1,1)到(p,q)的最短路径. 此时摆在小哼面前的路有两条,我们可以先让小哼往右边走,直到走不通的时候再回到这里,再去尝试另外一个方向. 在这里我们规定一

【BZOJ4942】[Noi2017]整数 线段树+DFS(卡过)

[BZOJ4942][Noi2017]整数 题目描述去uoj 题解:如果只有加法,那么直接暴力即可...(因为1的数量最多nlogn个) 先考虑加法,比较显然的做法就是将A二进制分解成log位,然后依次更新这log位,如果最高位依然有进位,那么找到最高位后面的第一个0,将中间的所有1变成0,那个0变成1.这个显然要用到线段树,但是复杂度是nlog2n的,肯定过不去. 于是我在考场上yy了一下,这log位是连续的,我们每次都要花费log的时间去修改一个岂不是很浪费?我们可以先在线段树上找到这段区间

uva1103(dfs)

UVA - 1103 还是没写好,,看的别人的 1 #include <iostream> 2 #include <cstdio> 3 #include <cmath> 4 #include <cstring> 5 #include <algorithm> 6 #include <cstdlib> 7 #include <stack> 8 #include <cctype> 9 #include <str