HDU1054(二分图)

Strategic Game

Time Limit: 20000/10000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)

Total Submission(s): 6941 Accepted Submission(s): 3263

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

因为给出的是一棵树,所以他一定可转化成一个二分图,那么问题就转化成求二分图的最小点覆盖(最小点覆盖:假如选了一个点就相当于覆盖了以它为端点的所有边,你需要选择最少的点来覆盖所有的边。),利用K?nig定理,它的意思是,一个二分图中的最大匹配数等于这个图中的最小点覆盖数。知道这个就变成模版题了,但是因为点比较多所以要用Hopcroft-Carp算法优化一波,试过用普通匈牙利算法TLE了。

/* *********************************************
二分图匹配(Hopcroft-Carp的算法)。
初始化:g[][]邻接矩阵
调用:res=MaxMatch();  Nx,Ny要初始化!!!
时间复杂大为 O(V^0.5 E)

适用于数据较大的二分匹配
需要queue头文件
********************************************** */
#include "cstring"
#include "cstdio"
#include "string.h"
#include "iostream"
#include "queue"
using namespace std;
const int MAXN=1510;
const int INF=1<<28;
int g[MAXN][MAXN],Mx[MAXN],My[MAXN],Nx,Ny;
int dx[MAXN],dy[MAXN],dis;
bool vst[MAXN];
bool searchP()
{
    queue<int>Q;
    dis=INF;
    memset(dx,-1,sizeof(dx));
    memset(dy,-1,sizeof(dy));
    for(int i=0;i<Nx;i++)
        if(Mx[i]==-1)
        {
            Q.push(i);
            dx[i]=0;
        }
    while(!Q.empty())
    {
        int u=Q.front();
        Q.pop();
        if(dx[u]>dis)  break;
        for(int v=0;v<Ny;v++)
            if(g[u][v]&&dy[v]==-1)
            {
                dy[v]=dx[u]+1;
                if(My[v]==-1)  dis=dy[v];
                else
                {
                    dx[My[v]]=dy[v]+1;
                    Q.push(My[v]);
                }
            }
    }
    return dis!=INF;
}
bool DFS(int u)
{
    for(int v=0;v<Ny;v++)
        if(!vst[v]&&g[u][v]&&dy[v]==dx[u]+1)
        {
            vst[v]=1;
            if(My[v]!=-1&&dy[v]==dis) continue;
            if(My[v]==-1||DFS(My[v]))
            {
                My[v]=u;
                Mx[u]=v;
                return 1;
            }
        }
    return 0;
}
int MaxMatch()
{
    int res=0;
    memset(Mx,-1,sizeof(Mx));
    memset(My,-1,sizeof(My));
    while(searchP())
    {
        memset(vst,0,sizeof(vst));
        for(int i=0;i<Nx;i++)
            if(Mx[i]==-1&&DFS(i))  res++;
    }
    return res;
}

int main()
{
    int n;
    while(~scanf("%d",&n))
    {
        memset(g,0,sizeof(g));
        Nx=Ny=n;
        for(int i=1;i<=n;i++)
        {
            int now,cnt;
            scanf("%d:(%d)",&now,&cnt);
            while(cnt--)
            {
                int temp;
                scanf("%d",&temp);
                g[now][temp]=1;
                g[temp][now]=1;
            }
        }
        printf("%d\n",MaxMatch()/2);
    }
}
时间: 2024-10-14 08:56:29

HDU1054(二分图)的相关文章

hdu1054(二分图匹配)

题意很简单,在一颗树上找最小点覆盖. 将树染成黑白两色,构成一张二分图,然后最大匹配==最小点覆盖即可,所以一次匈牙利就可以求出来了 hdu1054 #include <iostream> #include <stdio.h> #include <string.h> #include <math.h> #include <algorithm> #include <string> #include <queue> #incl

hdu1054 树形dp

http://acm.hdu.edu.cn/showproblem.php?pid=1054 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

二分图最小覆盖

hdu1150 最小顶点覆盖 hdu1498 50 years, 50 colors 最小顶点覆盖 +枚举 1 #include <iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 #include<stdlib.h> 6 #include<vector> 7 #include<cmath> 8 #include<queu

二分图匹配知识

二部图及其最大匹配: 二部图:对于无向图G(V,E),若能将其顶点分成V1,V2两个不相交的非空子集,使得G中的任何一条边的两个端点一个属于V1,另一个属于V2,那么该图就称为二部图. 性质:一个无向图G(V,E)是二部图当且仅当G中不存在长度为奇数的回路. 匹配:在图论中,一个「匹配」(matching)是一个边的集合,其中任意两条边都没有公共顶点.例如,图 3.图 4 中红色的边就是图 2 的匹配. 最大匹配:一个图所有匹配中,所含匹配边数最多的匹配,称为这个图的最大匹配.图 4 是一个最大

bzoj4025 二分图

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=4025 [题解] 考虑对时间分治,用可撤回的启发式合并并查集来维护连通性. 二分图的条件是没有奇环,用并查集判即可. 对于时间区间[l,r],如果边在这期间都存在,那么就加入并查集,对于剩下的边分类,并且分治下去做. 对于每条边,在log个区间表示出来了,需要进行判断,启发式合并的getf是log的,所以复杂度为O(nlog^2n) # include <stdio.h> # includ

POJ2584 T-Shirt Gumbo 二分图匹配(网络流)

1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 5 const int inf=0x3f3f3f3f; 6 const int sink=30; 7 8 struct Edge 9 { 10 int to; 11 int next; 12 int capacity; 13 14 void assign(int t,int n,int c) 15 { 16 to=t; next=n; ca

棋盘游戏(二分图匹配)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=1281 棋盘游戏 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 3200    Accepted Submission(s): 1897 Problem Description 小 希和Gardon在玩一个游戏:对一个N*M的棋盘,在格子里放

二分图【模板】

二分图:原图G的顶点可以分类两个集合X和Y,所有的边关联的两个顶点恰好一个属于集合X,另一个属于集合Y,则称该图为二分图. 二分图匹配:给定一个二分图G,在G的一个子图M中,M的边集中的任意两条边都不依附于同一个顶点,即一个顶点最多只有一条边.则称M是一个匹配. 二分图最大匹配:图中包含边数最多的匹配称为图的最大匹配. 二分图完美匹配:如果所有点都在匹配边上,则称这个最大匹配是完美匹配. 二分图多重匹配:二分图匹配一对一匹配,这里允许集合Y中的一个元素和集合X中的多个元素匹配(一般有最大限制N)

NYOJ 237 游戏高手的烦恼 &amp;&amp; POJ3041-Asteroids ( 二分图的最大匹配 )

链接: NYOJ 237  游戏高手的烦恼:click here~~ POJ  3041 Asteroids           :click here~~ 题意: 两题一样,翻译不同而已. 有一位传说级游戏高手,在闲暇时间里玩起了一个小游戏,游戏中,一个n*n的方块形区域里有许多敌人,玩家可以使用炸弹炸掉某一行或者某一列的所有敌人.他是种玩什么游戏都想玩得很优秀的人,所以,他决定,使用尽可能少的炸弹炸掉所有的敌人. 现在给你一个游戏的状态,请你帮助他判断最少需要多少个炸弹才能炸掉所有的敌人吧.