zoukankan      html  css  js  c++  java
  • (hdu step 6.3.1)Strategic Game(求用最少顶点数把全部边都覆盖,使用的是邻接表)

    题目:

    Strategic Game

    Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
    Total Submission(s): 110 Accepted Submission(s): 75
     
    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
     
    Recommend
    JGShining


    题目分析:

                   二分图,求最小顶点覆盖。简单题。这道题须要注意的是,用邻接矩阵来做会超时,数组开得太大,要用

    邻接表来做。

    最小顶点覆盖 = 最大匹配数/2


    代码例如以下:

    /*
     * a.cpp
     *
     *  Created on: 2015年3月13日
     *      Author: Administrator
     */
    
    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <vector>
    
    using namespace std;
    
    const int maxn = 1501;
    //bool map[maxn][maxn];//这个是使用邻接矩阵实现时所须要用到的数据结构
    vector<int> map[maxn];//这个是使用邻接表实现时所须要用到的数据结构.这时候map[i]里面村的就是愿意和结点i匹配的结点集合了
    bool useif[maxn];//用于标记某个节点是否已经匹配
    int link[maxn];//link[i] = t .表示结点i匹配的结点是t
    
    
    int n;//节点数
    
    /**
     * 用邻接表实现的,推断结点t能否找到匹配的节点
     */
    bool can(int t){
    	int i;
    
    	int size = map[t].size();//获取元一个结点t匹配的结点的个数
    	for(i = 0 ; i < size ; ++i){//遍历每个愿意和结点t匹配的结点
    		int index = map[t][i];//获取愿意和节点t匹配的结点的序号
    		if(useif[index] == false){//假设该节点还没有匹配
    			useif[index] = true;//将该节点标记为已经匹配
    			if(link[index] == - 1 || can(link[index])){//假设该节点还没有匹配的结点||该匹配结点能找到其它的匹配结点
    				link[index] = t;//那么僵该节点的匹配结点设置为t
    
    				return true;//返回true,表示可以t找到匹配的结点
    			}
    		}
    	}
    
    	return false;//返回false,表示结点t无法找到匹配的节点
    }
    
    
    /**
     * 求最大匹配数
     */
    int max_match(){
    	int num = 0;
    
    	int i;
    	for(i = 0 ; i < n ; ++i){//遍历全部节点,求最大匹配数
    		memset(useif,false,sizeof(useif));
    		if(can(i) == true){
    			num++;
    		}
    	}
    
    	return num;
    }
    
    
    int main(){
    	while(scanf("%d",&n)!=EOF){
    //		memset(map,false,sizeof(map));//使用邻接矩阵实现求最大匹配数时,清空map的写法
    		int i;
    
    		for(i = 0 ; i < n ; ++i){//使用邻接矩阵求最大匹配数时,清空map的写法
    			map[i].clear();
    		}
    		memset(link,-1,sizeof(link));
    
    		int a,b;
    		for(i = 0 ; i < n ; ++i){
    			scanf("%d:(%d)",&a,&b);
    
    			int c;
    			int j;
    			for(j = 0 ; j < b ; ++j){
    				scanf("%d",&c);
    //				map[a][c] = true;//邻接矩阵建立关系的写法
    //				map[c][a] = true;
    				/**
    				 * 这道题和Grils And Boys 的差别就在于
    				 * 假设0 (2): 1 2  --->这个表示0与1和2相互认识
    				 * 在Grils And Boys中,0会出如今1和2的描写叙述中如
    				 * 1  (...): 0 ...
    				 * 2  (...): 0 ...
    				 *
    				 * 可是这道题中0 (2): 1 2 表示的不过0认识1和2
    				 * 但1和2不一定认识0.
    				 * 在做的时候我们要把它转换成相互认识来做
    				 */
    				map[a].push_back(c);//邻接表建立关系的写法
    				map[c].push_back(a);
    			}
    		}
    
    		//最小顶点覆盖 = 最大匹配数/2
    		printf("%d
    ",max_match()/2);
    	}
    
    	return 0;
    }
    
    






  • 相关阅读:
    Linux 常用命令之df du
    Liunx 命令之链接操作
    1、SpringBoot bean,list,map Json返回
    Echarts 柱状图配置详解
    layui table数据表格reload where参数保留问题
    Mac休眠后解决卡死转圈问题
    5、Storm集成Kafka
    使用OData技术遇到的问题及解决办法
    我的柔情你永远不懂...
    如果你知道时间的默认值...
  • 原文地址:https://www.cnblogs.com/zfyouxi/p/5308088.html
Copyright © 2011-2022 走看看