【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,一经查实,立即删除!

相关文章

vue css自定义标签,Vue如何使用CSS自定义变量

目录在 css 自定义变量的功能以及出来许久了&#xff0c;但实际开发中大家使用并不多。归其原因是因为 less、sass 等预处理器已经拥有定义变量的功能&#xff0c;以及Vue、react很方便设置 style 样式&#xff0c;大家可能觉得使用 css 定义变量不方便且没必要。实则不然举个最…

【CodeForces - 260A】Adding Digits (思维构造)

题干&#xff1a; Vasya has got two number: a and b. However, Vasya finds number a too short. So he decided to repeat the operation of lengthening number a n times. One operation of lengthening a number means adding exactly one digit to the number (in the…

人工智能在fpga的具体应用_人工智能带动了FPGA的发展

未来几年&#xff0c;人工智能芯片的需求将急剧上升。联合市场研究公司(Allied Market Research)预估&#xff0c;未来5年&#xff0c;人工智能芯片的需求将以每年近50&#xff05;的速度增长&#xff0c;因为该技术将在汽车、医疗保健等多个领域得到广泛应用。Xilinx深知其中存…

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

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

【CodeForces - 260B 】Ancient Prophesy (暴力匹配,BF算法,日期字符串)

题干&#xff1a; A recently found Ancient Prophesy is believed to contain the exact Apocalypse date. The prophesy is a string that only consists of digits and characters "-". Well say that some date is mentioned in the Prophesy if there is a su…

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;下面就…

spring的beanutils工具类_基于spring-beans实现工具类BeanUtils基于Class实例化注入对象及查找方法、复制属性等操作...

一、前言基于spring-beans(4.1.4)的工具类org.springframework.beans.BeanUtils对注入spring对象按照Class实例化instantiateClass、class对象方法名称methodName查找findMethod、属性查找对于class类信息findPropertyType、对象属性复制copyProperties等常用操作&#xff0c;具…

【CodeForces - 260C】Balls and Boxes (思维模拟,有坑,时光倒流)

题干&#xff1a; Little Vasya had n boxes with balls in the room. The boxes stood in a row and were numbered with numbers from 1 to n from left to right. Once Vasya chose one of the boxes, lets assume that its number is i, took all balls out from it (it …

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

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

java生日正则表达式_java之正则表达式、日期操作

正则表达式和日期操作正则表达式简介正则表达式就是使用一系列预定义的特殊字符来描述一个字符串的格式规则&#xff0c;然后使用该格式规则匹配某个字符串是否符合格式要求。作用:比如注册邮箱,邮箱有用户名和密码,一般会对其限制长度,这个限制长度的事情就是正则表达式做的规…

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

如何用服务器做渲染 内容精选换一换&#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…

读取ppt并存入数据库_Java解析Excel文件并把数据存入数据库

前段时间做一个小项目&#xff0c;为了同时存储多条数据&#xff0c;其中有一个功能是解析Excel并把其中的数据存入对应数据库中。花了两天时间&#xff0c;不过一天多是因为用了"upload"关键字作为URL从而导致总报同一个错&#xff0c;最后在同学的帮助下顺利解决&a…

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

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

【POJ - 3041】Asteroids (二分图,最小点覆盖)

题干&#xff1a; Bessie wants to navigate her spaceship through a dangerous asteroid field in the shape of an N x N grid (1 < N < 500). The grid contains K asteroids (1 < K < 10,000), which are conveniently located at the lattice points of the…

华为虚拟服务器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;再重启就可以了。…

【 POJ - 2033 】Alphacode (dp,有坑)

题干&#xff1a; Alice and Bob need to send secret messages to each other and are discussing ways to encode their messages: Alice: "Lets just use a very simple code: Well assign A the code word 1, B will be 2, and so on down to Z being assigned 26.&…

两组的数据平均值合并_不要进入数据陷进

学习统计让我们不再被一些数据迷惑进入数据陷进&#xff08;例如平均工资&#xff09;从而做出正确的决策。描述性统计分析包括数据的分布、集中、波动的测度指标。平均值&#xff1a;一组数据的加和除以数据的个数&#xff08;容易随极端值变化&#xff09; 中位数&#xff1a…