luogu P3942 将军令

题目背景

pdf题面和大样例链接:http://pan.baidu.com/s/1cawM7c 密码:xgxv

 历史/落在/赢家/之手
 至少/我们/拥有/传说
 谁说/败者/无法/不朽
 拳头/只能/让人/低头
 念头/却能/让人/抬头
 抬头/去看/去爱/去追
 你心中的梦   

题目描述

又想起了四月。

如果不是省选,大家大概不会这么轻易地分道扬镳吧? 只见一个又一个昔日的队友离开了机房。

凭君莫话封侯事,一将功成万骨枯。

梦里,小 F 成了一个给将军送密信的信使。

现在,有两封关乎国家生死的密信需要送到前线大将军帐下,路途凶险,时间紧迫。小 F 不因为自己的祸福而避趋之,勇敢地承担了这个任务。

不过,小 F 实在是太粗心了,他一不小心把两封密信中的一封给弄掉了。

小 F 偷偷打开了剩下的那封密信。他 发现一副十分详细的地图,以及几句批文——原来 这是战场周围的情报地图。他仔细看后发现,在这张地图上标记了 n 个从 1 到 n 标号的 驿站,n − 1 条长度为 1 里的小道,每条小道双向连接两个不同的驿站,并且驿站之间可以 通过小道两两可达。

小 F 仔细辨认着上面的批注,突然明白了丢失的信的内容了。原来,每个驿站都可以驻 扎一个小队,每个小队可以控制距离不超过 k 里的驿站。如果有驿站没被控制,就容易产 生危险——因此这种情况应该完全避免。而那封丢失的密信里,就装着朝廷数学重臣留下的 精妙的排布方案,也就是用了最少的小队来控制所有驿站。

小 F 知道,如果能计算出最优方案的话,也许他就能够将功赎过,免于死罪。他找到了 你,你能帮帮他吗? 当然,小 F 在等待你的支援的过程中,也许已经从图上观察出了一些可能会比较有用的 性质,他会通过一种特殊的方式告诉你。

输入输出格式

输入格式:

 

从标准输入中读入数据。

输入第 1 行一个正整数 n,k,t,代表驿站数,一支小队能够控制的最远距离,以及特 殊性质所代表的编号。关于特殊性质请参照数据范围。

输入第 2 行至第 n 行,每行两个正整数 u_iui?,v_ivi?,表示在 u_iui? 和 v_ivi? 间,有一条长度为 一里的小道。

 

输出格式:

 

输出到标准输出中。

输出一行,为最优方案下需要的小队数。

 

输入输出样例

输入样例#1: 复制

4 1 0
1 2
1 3
1 4

输出样例#1: 复制

1
 

 

 

输入样例#2: 复制

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

输出样例#2: 复制

2

 

 

 

 

 

说明

【样例 1 说明】

如图。由于一号节点到周围的点距离均是 1,因此可以控制所有驿站。

【样例 2 说明】

如图,和样例 1 类似。

子任务会给出部分测试数据的特点。如果你在解决题目中遇到了困难,可以尝试只解 决一部分测试数据。

关于 t 的含义如下: t = 0:该测试点没有额外的特殊性质; t = 1:保证最多 8 个点的所连接的小道超过 1 条; t = 2:保证所有点到 1 号点的距离不超过 2。

每个测试点的数据规模及特点如下表

题目链接:https://www.luogu.org/problemnew/show/P3942#sub

解题报告:

低配版消防局

bfs+dfs+贪心

从最深处开始贪心,将其k祖先作为驿站,进行dfs

#include<cstdio>
#include<queue>
#include<algorithm>
#include<iostream>
#define BIG 2000011
#define ll long long
#define FOR(i,s,t) for(register int i=s;i<=t;++i)
using namespace std;
int nxt[BIG],las[BIG>>1],to[BIG],a[BIG>>1],dep[BIG>>1],fa[BIG>>1],vis[BIG>>1];
int n,k,t,f;
int x,y,ans,tot;
inline void add(int x,int y){
	nxt[++tot]=las[x];las[x]=tot;to[tot]=y;
}
#define VIS(now) for(register int e=las[now];e;e=nxt[e])
inline void bfs(int x){
	queue<int>q;
	dep[x]=1;
	fa[1]=1;
	q.push(x);
	int now;
	while(!q.empty()){
		now=q.front();
		q.pop();
		VIS(now)
			if(!dep[to[e]])
				fa[to[e]]=now,dep[to[e]]=dep[now]+1,q.push(to[e]);
	}
}
inline bool cmp(int a,int b){
	return dep[a]>dep[b];
}
inline int up(int x){
	int cnt=0;
	while(cnt<k){
		x=fa[x];
		++cnt;
	}
	return x;
}
inline void dfs(int now,int fa,int tot){
	vis[now]=1;
	if(tot==k)
		return;
	VIS(now)
		if(to[e]!=fa)
			dfs(to[e],now,tot+1);
}
int main(){
	scanf("%d%d%d",&n,&k,&t);
	FOR(i,2,n){
		scanf("%d%d",&x,&y);
		add(x,y);
		add(y,x);
	}
	bfs(1);
	FOR(i,1,n)
		a[i]=i;
	sort(a+1,a+n+1,cmp);
	FOR(i,1,n)
		if(!vis[a[i]]){
			++ans;
			f=up(a[i]);
			dfs(f,f,0);
		}
	printf("%d\n",ans);
	return 0;
}

  

时间: 2024-11-07 16:16:26

luogu P3942 将军令的相关文章

P3942 将军令

P3942 将军令 梦里,小 F 成了一个给将军送密信的信使. 现在,有两封关乎国家生死的密信需要送到前线大将军帐下,路途凶险,时间紧迫.小 F 不因为自己的祸福而避趋之,勇敢地承担了这个任务. 不过,小 F 实在是太粗心了,他一不小心把两封密信中的一封给弄掉了. 小 F 偷偷打开了剩下的那封密信.他 发现一副十分详细的地图,以及几句批文--原来 这是战场周围的情报地图.他仔细看后发现,在这张地图上标记了 n 个从 1 到 n 标号的 驿站,n ? 1 条长度为 1 里的小道,每条小道双向连接两

将军令 Luogu P3942

pdf题面和大样例链接:http://pan.baidu.com/s/1cawM7c 密码:xgxv 历史/落在/赢家/之手 至少/我们/拥有/传说 谁说/败者/无法/不朽 拳头/只能/让人/低头 念头/却能/让人/抬头 抬头/去看/去爱/去追 你心中的梦 将军令 题目描述 又想起了四月. 如果不是省选,大家大概不会这么轻易地分道扬镳吧? 只见一个又一个昔日的队友离开了机房. 凭君莫话封侯事,一将功成万骨枯. 梦里,小 F 成了一个给将军送密信的信使. 现在,有两封关乎国家生死的密信需要送到前线

【贪心】P3942 将军令 &amp;&amp; P2279 消防局的设立

1.消防局的设立 题目描述 2020年,人类在火星上建立了一个庞大的基地群,总共有n个基地.起初为了节约材料,人类只修建了n-1条道路来连接这些基地,并且每两个基地都能够通过道路到达,所以所有的基地形成了一个巨大的树状结构.如果基地A到基地B至少要经过d条道路的话,我们称基地A到基地B的距离为d. 由于火星上非常干燥,经常引发火灾,人类决定在火星上修建若干个消防局.消防局只能修建在基地里,每个消防局有能力扑灭与它距离不超过2的基地的火灾. 你的任务是计算至少要修建多少个消防局才能够确保火星上所有

luogu P3799 妖梦拼木棒

二次联通门 : luogu P3799 妖梦拼木棒 /* luogu P3799 妖梦拼木棒 用一个桶存下所有的木棒 美剧两根短的木棒长度 后随便乘一乘就 好了.. */ #include <algorithm> #include <cstdio> #define Mod 1000000007 #define Max 5000 void read (int &now) { now = 0; register char word = getchar (); while (wo

[luogu P1967][NOIp2013]P1967 货车运输

题目描述 A 国有 n 座城市,编号从 1 到 n,城市之间有 m 条双向道路.每一条道路对车辆都有重量限制,简称限重.现在有 q 辆货车在运输货物, 司机们想知道每辆车在不超过车辆限重的情况下,最多能运多重的货物. 输入输出格式 输入格式: 输入文件名为 truck.in. 输入文件第一行有两个用一个空格隔开的整数 n,m,表示 A 国有 n 座城市和 m 条道 路. 接下来 m 行每行 3 个整数 x. y. z,每两个整数之间用一个空格隔开,表示从 x 号城市到 y 号城市有一条限重为 z

luogu 3126 回文的路径

https://www.luogu.org/problem/show?pid=3126 考虑dp,从两头走到中间. f[i][j][k][l]表示从左上角走到(i,j),从右下角走到(k,l),路径长度相等,所经过路径相同的方案数. 方程不再赘述. 考虑步数要相同,所以只要枚举步数和行就好. f[i][j][k]表示第一个点在第j行,第2个点在第k行,走i步的方案数. 所以得出方程f[i][j][k]=(f[i-1][j-1][k]+f[i-1][j][k+1]+f[i-1][j-1][k+1]

luogu P2018 消息传递

二次联通门 : luogu P2018 消息传递 /* luogu P2018 消息传递 树形dp 原来用优先队列做了一下, T了俩点 MMP 去看正解.. 复杂度一样好不好.. 每次到达一个点,记录其子树中所有的dp值 优先向大的一边转移 */ #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> #define INF 1e8 const int BUF

luogu P1966 火柴排队

二次联通门 : luogu P1966 火柴排队 /* luogu P1966 火柴排队 神TM逆序对... noip怎么这么坑啊.. 暴力都没得打 此题模拟考试时爆了0 做法 将A数组排序,由于B数组与A数组是一一对应的 那么B数组的位置也会发生相应的变化 此时B数组逆序数对数即为答案 */ #include <cstdio> #include <iostream> #include <algorithm> const int BUF = 123123123; cha

luogu P1941 飞扬的小鸟

二次联通门 : luogu P1941 飞扬的小鸟 /* luogu P1941 飞扬的小鸟 dp 向上飞是完全背包,向下掉就是01背包 分情况讨论一下 最后合并一下 */ #include <cstdio> #include <iostream> #include <cstring> const int BUF = 123123123; char Buf[BUF], *buf = Buf; inline void read (int &now) { for (