【POJ - 1463】Strategic game (树上最小点覆盖,树形dp)

题干:

Bob enjoys playing computer games, especially strategic games, but sometimes he cannot find the solution fast enough and then he is very sad. Now he has the following problem. He must defend a medieval city, the roads of which form a tree. He has to put the minimum number of soldiers on the nodes so that they can observe all the edges. Can you help him? 

Your program should find the minimum number of soldiers that Bob has to put for a given tree. 

For example for the tree: 


the solution is one soldier ( at the node 1).

Input

The input contains several data sets in text format. Each data set represents a tree with the following description: 

  •  
  • the number of nodes 
  • the description of each node in the following format 
    node_identifier:(number_of_roads) node_identifier1 node_identifier2 ... node_identifiernumber_of_roads 
    or 
    node_identifier:(0) 


The node identifiers are integer numbers between 0 and n-1, for n nodes (0 < n <= 1500);the number_of_roads in each line of input will no more than 10. Every edge appears only once in the input data.

Output

The output should be printed on the standard output. For each given input data set, print one integer number in a single line that gives the result (the minimum number of soldiers). An example is given in the following:

Sample Input

4
0:(1) 1
1:(2) 2 3
2:(0)
3:(0)
5
3:(3) 1 4 2
1:(1) 0
2:(0)
0:(0)
4:(0)

Sample Output

1
2

题目大意:

给出一个n个结点的树,要求选出其中的一些顶点,使得对于树中的每条边(u, v),u和v至少有一个被选中. 请给出选中顶点数最少的方案. 

解题报告:

    树形图的最小点覆盖、、、直接跑匈牙利也可以过,大概是数据水了。

AC代码:

#include<cstdio>
#include<iostream>
#include<algorithm>
#include<queue>
#include<map>
#include<vector>
#include<set>
#include<string>
#include<cmath>
#include<cstring>
#define ll long long
#define pb push_back
#define pm make_pair
#define fi first
#define se second
using namespace std;
const int MAX = 2e5 + 5;
int n;
vector<int> vv[1505];
int dp[1505][2];
void dfs(int cur,int root) {int up = vv[cur].size();
//	if(up == 1) {dp[cur][1]=1;
//	}for(int i = 0; i<up; i++) {int v = vv[cur][i];if(v == root) continue;dfs(v,cur);dp[cur][0] += dp[v][1];dp[cur][1] += min(dp[v][0],dp[v][1]);}
}
int main()
{int x,num,y;while(~scanf("%d",&n)) {for(int i = 0; i<=n; i++) vv[i].clear();memset(dp,0,sizeof dp);for(int i = 1; i<=n; i++) {scanf("%d:(%d)",&x,&num);if(num == 0) continue;while(num--) {scanf("%d",&y);vv[x].pb(y);vv[y].pb(x);}}//dfs(vv[0][0],0);dfs(0,0);printf("%d\n",min(dp[0][0],dp[0][1]));}return 0 ;}

总结:

   几个要注意的地方:

       首先别忘了是从0号点开始编号!!所以vv的初始化要从i=0开始!

      第二那个if num==0  可以不加、

      第三这题双向图单向图都可以做,一般习惯双向图然后dfs中加一个参数root就行了。。。而且main函数调用的时候不需要管root传什么值(实在不行给个-1,,反正用不到这个),,直接(0,0)或者(1,1)都行。。。(当然最好还是传(0,0)。因为这题是恰好了没有单个顶点的情况,万一有这种特例,那就WA了啊)

 

AC代码2:(分析一下)

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cmath>
#define PI acos(-1.0)using namespace std;
typedef long long ll;
const int maxn = 1500+7, INF = 0x3f3f3f3f;
int n, cur, ans;
int f[maxn];
bool vis[maxn];
int next[maxn];
struct edge {int v, bef;
} e[maxn*2];
void add(int x, int y) {e[cur].v = y;e[cur].bef = next[x];next[x] = cur++;
}
void init() {memset(next, -1, sizeof(int)*(n+1));cur = 1;for(int j = 0; j < n; ++j) {int u, v, cnt;scanf("%d:(%d)", &u, &cnt);for(int i = 0; i < cnt; ++i) {scanf("%d", &v);add(u, v);add(v, u);//a[u].push_back(v);//a[v].push_back(u);}}memset(f, -1, sizeof(int)*(n+1));
}
bool dfs(int id) {for(int i = next[id]; i != -1; i = e[i].bef) {if(!vis[e[i].v]) {vis[e[i].v] = 1;if(f[e[i].v] == -1 || dfs(f[e[i].v])) {f[id] = e[i].v;f[e[i].v] = id;return true;}}}return false;
}
int main() {while(scanf("%d", &n) != EOF && n) {init();ans = 0;for(int i = 0; i < n; ++i) {if(f[i] == -1) {memset(vis, false, sizeof(bool)*(n+1));if(dfs(i)) ans++;}}printf("%d\n", ans);}return 0;
}

我们来分析一下这份冗长的代码(网上找的,上面这份是原始代码)首先他用f数组(也就是nxt)数组同时记录了两个的值(与这个题不同【HDU - 1281 】棋盘游戏,那个题的AC代码2 是 用两个数组分别记录左侧的值和右侧的值的,,而这个题的这种解法是都存在同一个数组f中)所以我们要想直接输出ans而不是ans/2的话,就需要判断一步  :(   if(f[i] != -1)则进入循环 )。如果去掉这个if的话,最后还是要输出ans/2的,,因为相当于还是每个点都搜了一遍,,原来的匹配会被覆盖的,,所以加这个if的话,会减少一半的复杂度(其实也没多少、。、还是那个数量级)(其实我也不太懂,,,不加这个if,,为什么不会wa??我感觉会WA的啊)其实这题跑匈牙利的话直接建双向边上模板就好了。。。就是个拆点

 

下面是个完整的匈牙利代码:(改天可以自己再写一遍)

其实之所以可以跑二分匹配,是因为它其实是个二分图。(所以可以“拆点”(伪拆点)求最大匹配!!!)想想为啥是个二分图。

#include <stdio.h>
#include <string.h>
#include <vector>
#include <algorithm>
#define maxn 210
const int INF=0x3f3f3f3f;
using namespace std;
int n;
vector<int>g[1510];
int used[1510],match[1510];
int dfs(int x)
{int i;for(i=0;i<g[x].size();i++){int k=g[x][i];if(!used[k]){used[k]=1;if(match[k]==-1||dfs(match[k])){match[k]=x;return 1;}}}return 0;
}
int main ()
{int i,j,a,b,k;while(scanf("%d",&n)!=EOF){int ans=0;memset(g,0,sizeof(g));for(i=1;i<=n;i++){scanf("%d:(%d)",&a,&k);while(k--){scanf("%d",&b);g[a].push_back(b);g[b].push_back(a);}}memset(match,-1,sizeof(match));for(i=0;i<n;i++){memset(used,0,sizeof(used));if(dfs(i))ans++;}printf("%d\n",ans/2);}return 0;
}

附:

https://blog.csdn.net/Ema1997/article/details/51870453

不知道这个代码为什么找第一个flag=0的点进行dfs。、。。感觉随便找个点dfs就可以啊,所以0号点就好了啊。

 

一个看不懂的代码:大概是找增广路的方法。匹配变成不匹配。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/441209.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

恐怖黎明稳定服务器,恐怖黎明新人联机图文教程 怎么联机-游侠网

恐怖黎明怎么联机?不少玩家想体验联机&#xff0c;但是不知道方法&#xff0c;小编这里给大家带来了新人联机图文教程&#xff0c;不会的萌新来学习下吧。联机图文教程:A1 联机&#xff1a;因为gd(grimdawn)没有自己的战网平台(就是专供联机玩的专职服务器 server)&#xff0c…

github 上传代码_leetcode爬虫:爬取代码;生成readme;上传github

Leetcode-Helper哪个程序员 不想一键下写过的代码&#xff0c;自动上传Github&#xff0c;并且还能生成好看的README呢&#xff1f;有用的话点个⭐吧&#xff0c;谢谢你。Leetcode-Helper传送门​github.com主要功能 模拟登陆力扣中国站(leetcode-cn)爬取每题提交的ac代码&…

绝地求生信号枪只能在服务器吗,绝地求生信号枪怎么用?信号枪刷新点及用法详解...

绝地求生信号枪怎么用&#xff1f;信号枪刷新点及用法详解2018-03-15 15:22:12来源&#xff1a;吃鸡小助手编辑&#xff1a;野狐禅评论(0)绝地求生近日更新中悄悄加入了信号枪&#xff0c;引得广大玩家热情满满的在游戏中寻找&#xff0c;信号枪到底怎么用呢&#xff1f;下面就…

文件服务器共享文件夹访问权限,5对文件服务器中的共享文件夹进行访问权限控制...

对文件服务器中的共享文件夹进行访问权限控制1. 实训目的在Windows Server 2003环境下设置文件服务器的目的是要对多用户进行资源共享&#xff0c;这其中经常遇到不同用户应该分配不同权限的问题&#xff0c;通过这个实训希望读者了解Windows Server 2003中访问权限设置方法和具…

渲染服务器位置,如何用服务器做渲染

如何用服务器做渲染 内容精选换一换&#xfffd;&#xfffd;&#xfffd;&#xfffd;BoostKit ARMԭ&#xfffd;&#xfffd;ʹ&#xfffd;&#xfffd;&#xfffd;׼&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;&#xfffd;嵥&#xfffd;&#xfffd…

【HDU - 2376】Average distance (树,平均距离,算贡献)

题干&#xff1a; Given a tree, calculate the average distance between two vertices in the tree. For example, the average distance between two vertices in the following tree is (d 01 d 02 d 03 d 04 d 12 d 13 d 14 d 23 d 24 d 34)/10 (63799131510122)/10…

两台虚拟服务器如何级联,[教程] 利用open vswitch建立vxlan隧道实现不同主机上的虚拟交换机级联...

写在开头在某些环境下&#xff0c;需要实现两台物理机中的openvswitch交换机级联&#xff0c;以实现两台交换机中的设备互相通讯&#xff0c;这里使用vxlan隧道技术&#xff0c;将数据包封装在UDP中&#xff0c;通过以太网实现数据包传输。VXLAN是一种大二层的虚拟技术&#xf…

华为虚拟服务器lanip地址,2018软考网络工程师《华为基础实验》十九配置路由器为DHCPServer...

原标题&#xff1a;2018软考网络工程师《华为基础实验》十九配置路由器为DHCPServer实验要求:在R1上使能DHCP 功能。创建三个全局地址池&#xff0c;用于为三个不同部门的PC分配IP 地址。配置地址池的相关属性。在R1的接口下配置基于全局地址池的服务方式&#xff0c;实现DHCP …

电脑重启bootmgr_电脑系统启动:显示0xc0000428怎么办

错误代码&#xff1a;0xc0000428 一般都是驱动问题&#xff0c;只需要找到报错的路径驱动程序&#xff0c;删除再重启就基本上可以解决了。制作一个U盘启动&#xff0c;进入PE&#xff0c;然后删除”\Windoiws\System32\drivers\DsArk64.sys“文件&#xff0c;再重启就可以了。…

安川西格玛7驱动器手册_什么是伺服驱动器?选型的原则有哪些?

头条号私信回复1&#xff0c;获取海量免费学习资源&#xff0c;内容包括自动化电气工程师必备的软件、电子书、视频教程等题图&#xff1a;伺服驱动器来源&#xff1a;百度图片什么是伺服驱动器&#xff1f;该如何选型&#xff1f;有哪些主流品牌&#xff1f;你想知道的全在这里…

java猜数游戏图形界面_Java做一个猜数的小游戏

Author &#xff1a; By Runsen效果展现猜数字游戏是一个简单&#xff0c;有趣的小游戏。游戏者通过输入一个指定区间的数字&#xff0c;与系统产生的随机数进行对比&#xff0c;然后输出相应的结果。游戏运行时产生一个0&#xff0d;10之间的随机整数&#xff0c;要求用户从控…

【CodeForces - 264A】Escape from Stones (模拟,卡精度的处理)

题干&#xff1a; Squirrel Liss lived in a forest peacefully, but unexpected trouble happens. Stones fall from a mountain. Initially Squirrel Liss occupies an interval [0, 1]. Next, nstones will fall and Liss will escape from the stones. The stones are nu…

【CodeForces - 270A】Fancy Fence (几何,思维,水题)

题干&#xff1a; Emuskald needs a fence around his farm, but he is too lazy to build it himself. So he purchased a fence-building robot. He wants the fence to be a regular polygon. The robot builds the fence along a single path, but it can only make fenc…

判断集合相等_数学启蒙的每个关键阶段之集合分类

本文我们将分享数学启蒙学什么&#xff1f;用几个字简单的归纳为集合、数、量、形、时间、空间。我们接下来会讲感知集合和分类&#xff0c;数概念&#xff0c;量的概念&#xff0c;形状包含平面图形和立体图形&#xff0c;空间方位和时间的初步概念。 家长们可以发现幼儿数学启…

【CodeForces - 270C】Magical Boxes (思维,进制,有坑)

题干&#xff1a; Emuskald is a well-known illusionist. One of his trademark tricks involves a set of magical boxes. The essence of the trick is in packing the boxes inside other boxes. From the top view each magical box looks like a square with side leng…

虚拟机安装黑群晖_【群晖系统】HEI群辉DSM 6.2.1 系统安装图文教程 (19年2月)

黑群晖系统其实是指在普通电脑运行Synology DSM系统, 事实上在普通PC电脑上安装黑群晖(Synology DSM)也非常方便, 现在把教程简单写一下。引导系统装哪里&#xff1f;非常关键的问题&#xff0c;DSM采用系统和数据相分离的结构&#xff0c;也就是说引导系统需要独立安装在一个设…

mysql 主从 keepalived_MySQL之双向主从加keepalived高可用

最近在做MySQL数据库的双向主从&#xff0c;了解到keepalived能够自动判断并切换到可用数据库&#xff0c;自己试了一下&#xff0c;整理出文档来。先声明一下环境iptables开启3306端口或者关掉&#xff0c;关闭selinuxMySQL-01&#xff1a;192.168.204.138MySQL-02&#xff1a…

docker启动mysql容器_Docker容器开机自启动

查看所有容器[vagrantlocalhost ~]$ sudo docker ps -a CONTAINER ID IMAGE COMMAND CREATED STATUS PORTS NAMES 3f142f72d7e8 redis "docker-entr…

【CodeForces - 527C】Glass Carving(线段树或者SBT或者set)

题干&#xff1a; Leonid wants to become a glass carver (the person who creates beautiful artworks by cutting the glass). He already has a rectangular w mm    h mm sheet of glass, a diamond glass cutter and lots of enthusiasm. What he lacks is understand…

mysql常驻内存_MySQL的内存和相关问题排查

我们都知道数据库是IO密集型一类应用&#xff0c;为了提高其性能大量使用内存代替文件(交换分区)的IO操作是保证数据库稳定、高效的基本原则。那么数据库是如何使用内存的&#xff0c;我们如何查看数据库内存的占用&#xff0c;如何通过通过数据库内存配置设置提高其性能&#…