HDU1054(KB10-H 最小顶点覆盖)

Strategic Game

Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 8503    Accepted Submission(s): 4093

Problem Description

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.

The input file 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_identifier
or
node_identifier:(0)

The node identifiers are integer numbers between 0 and n-1, for n nodes (0 < n <= 1500). Every edge appears only once in the input data.

For example for the tree:

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

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 table:

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

Source

Southeastern Europe 2000

最小顶点覆盖,拆点将问题转化为二分图的最小顶点覆盖。

定理:二分图最小顶点覆盖 == 最大匹配

  1 //2017-08-26
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <iostream>
  5 #include <algorithm>
  6
  7 using namespace std;
  8
  9 const int N = 5000;
 10 const int M = 1000000;
 11 int head[N], tot;
 12 struct Edge{
 13     int to, next;
 14 }edge[M];
 15
 16 void init(){
 17     tot = 0;
 18     memset(head, -1, sizeof(head));
 19 }
 20
 21 void add_edge(int u, int v){
 22     edge[tot].to = v;
 23     edge[tot].next = head[u];
 24     head[u] = tot++;
 25
 26     edge[tot].to = u;
 27     edge[tot].next = head[v];
 28     head[v] = tot++;
 29 }
 30
 31 int n;
 32 int matching[N];
 33 int check[N];
 34
 35 bool dfs(int u){
 36     for(int i =  head[u]; i != -1; i = edge[i].next){
 37         int v = edge[i].to;
 38         if(!check[v]){//要求不在交替路
 39             check[v] = 1;//放入交替路
 40             if(matching[v] == -1 || dfs(matching[v])){
 41                 //如果是未匹配点,说明交替路为增广路,则交换路径,并返回成功
 42                 matching[u] = v;
 43                 matching[v] = u;
 44                 return true;
 45             }
 46         }
 47     }
 48     return false;//不存在增广路
 49 }
 50
 51 //hungarian: 二分图最大匹配匈牙利算法
 52 //input: null
 53 //output: ans 最大匹配数
 54 int hungarian(){
 55     int ans = 0;
 56     memset(matching, -1, sizeof(matching));
 57     for(int u = 0; u < n; u++){
 58         if(matching[u] == -1){
 59             memset(check, 0, sizeof(check));
 60             if(dfs(u))
 61               ans++;
 62         }
 63     }
 64     return ans;
 65 }
 66
 67 int main()
 68 {
 69     std::ios::sync_with_stdio(false);
 70     //freopen("inputH.txt", "r", stdin);
 71     string str;
 72     while(cin>>n){
 73         init();
 74         int u, k, v;
 75         for(int i = 0; i < n; i++){
 76             cin>>str;
 77             u = 0, k = 0;
 78             int ptr = 0;
 79             while(str[ptr] != ‘:‘){
 80                 u *= 10;
 81                 u += str[ptr]-‘0‘;
 82                 ptr++;
 83             }
 84             ptr+=2;
 85             while(str[ptr] != ‘)‘){
 86                 k *= 10;
 87                 k += str[ptr]-‘0‘;
 88                 ptr++;
 89             }
 90             for(int j = 0; j < k; j++){
 91                 cin>>v;
 92                 add_edge(u, n+v);
 93                 add_edge(v, n+u);
 94             }
 95         }
 96         cout<<hungarian()/2<<endl;
 97     }
 98
 99     return 0;
100 }
时间: 2024-08-01 10:30:44

HDU1054(KB10-H 最小顶点覆盖)的相关文章

hdu1054(最小顶点覆盖)

传送门:Strategic Game 题意:用尽量少的顶点来覆盖所有的边. 分析:最小顶点覆盖裸题,最小顶点覆盖=最大匹配数(双向图)/2. #include <cstdio> #include <cstring> #include <string> #include <cmath> #include <iostream> #include <algorithm> #include <queue> #include <

hdu1054最小顶点覆盖

最小定点覆盖是指这样一种情况: 图G的顶点覆盖是一个顶点集合V,使得G中的每一条边都接触V中的至少一个顶点.我们称集合V覆盖了G的边.最小顶点覆盖是用最少的顶点来覆盖所有的边.顶点覆盖数是最小顶点覆盖的大小. 相应地,图G的边覆盖是一个边集合E,使得G中的每一个顶点都接触E中的至少一条边.如果只说覆盖,则通常是指顶点覆盖,而不是边覆盖. 在二分图中:最大匹配数=最小顶点覆盖数: Bob enjoys playing computer games, especially strategic gam

hdoj 1150 Machine Schedule【匈牙利算法+最小顶点覆盖】

Machine Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 6701    Accepted Submission(s): 3358 Problem Description As we all know, machine scheduling is a very classical problem in comput

poj3041 Asteroids(二分图最小顶点覆盖、二分图匹配)

Description 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

hdu 1150 Machine Schedule(最小顶点覆盖)

pid=1150">Machine Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5424    Accepted Submission(s): 2691 Problem Description As we all know, machine scheduling is a very classical pro

【二分图入门专题1】C - Machine Schedule hdu1150 【最小顶点覆盖】

As we all know, machine scheduling is a very classical problem in computer science and has been studied for a very long history. Scheduling problems differ widely in the nature of the constraints that must be satisfied and the type of schedule desire

hdu 1150 Machine Schedule(二分图-最小顶点覆盖)

Machine Schedule Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 5424    Accepted Submission(s): 2691 Problem Description As we all know, machine scheduling is a very classical problem in compu

HDU ACM 1054 Strategic Game 二分图最小顶点覆盖?树形DP

分析:这里使用树形DP做. 1.最小顶点覆盖做法:最小顶点覆盖 == 最大匹配(双向图)/2. 2.树形DP: dp[i][0]表示i为根节点,并且该节点不放,所需的最少的点数. dp[i][1]表示i为根节点,并且该节点放,所需要的最少的点数. dp[i][0]=sum(dp[son[i][j]][1]) 该点不放,则它的儿子节点必须都放,只有这样之间的边才可以被覆盖. dp[i][1]=sum(min(dp[son[i][j]][0],dp[son[i][j]][1])) 该点放的话,则它的

hdu 1054 Strategic Game (最小顶点覆盖+稀疏图)

Strategic Game Time Limit: 20000/10000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4889    Accepted Submission(s): 2225 Problem Description Bob enjoys playing computer games, especially strategic games, but some