hdu1054 Strategic Game(最小顶点覆盖)

来源:互联网 发布:怎么恢复数据 编辑:程序博客网 时间:2024/05/16 15:22


http://acm.hdu.edu.cn/showproblem.php?pid=1054

题意:Bob想要保卫一个中世纪城市,每个节点可以放一个工兵,每个工兵只能从一条路的一端打向另一端,如果这个节点相连多个边,那么与之相连的点工兵都可以保卫到。所有的道路组成一颗树,求可以保卫这棵树所需要的最少工兵数是多少。


ps:刚学了匈牙利算法,就是那个趣写教程,太火了就不上链接了。整体思路就是遍历每个点,看这个节点是否可以找到对应的匹配。

每个点的匹配过程中,遍历该点所想匹配的所有点。如果在本次递归内没有访问过,那就对此点访问,若访问过则遍历下一个相匹配的点。

可以访问后,就查看自己想匹配点的状态,满足这两种状态的任意一种都可以找到匹配:

(1)、想匹配的点还是单身狗;

(2)、想匹配的点已经有原配,那就试着拆原配,让原配去找小三。而找小三的人又可能去拆别人原配,这是一个递归。不过只要有一个人找到了小三,那别人也找到了小三,原配成功被小三拐走,想匹配的点重新变成单身狗。(为毛感觉画风突变= =)

若本次匹配失败,则遍历下一个想匹配的点(总不能在一棵树上吊死吧,想追就去追)。

若全部匹配都失败,那恭喜你汪汪汪了。


思路:最小顶点覆盖。可以转化为二分匹配模型,二分图中最小顶点覆盖数=最大匹配。详细可以看看我的理解。由于是无向图那么实际上两边的节点就是一样的,最后求出二分匹配数除以2即可。


#include <stdio.h>#include <algorithm>#include <stdlib.h>#include <string.h>#include <iostream>#include <queue>#include <stack>#include <ctype.h>using namespace std;typedef long long LL;const int N = 1505;const int INF = 0x3f3f3f3f;int head[N], match[N];bool vis[N];//vis代表某节点允许匹配的节点中在本次递归中是否被访问过int n, m, cnt;struct Edge{    int to,next;}edge[N*N];void add(int u, int v){    edge[cnt] = (struct Edge){v, head[u]};    head[u] = cnt++;    edge[cnt] = (struct Edge){u, head[v]};    head[v] = cnt++;}void init(){    cnt = 0;    memset(head, -1, sizeof(head));}bool Augment(int n, int u){    for(int i = head[u]; i != -1; i = edge[i].next)    {        int v = edge[i].to;        if(!vis[v])        {            vis[v] = true;            if(match[v]==-1 || Augment(n, match[v]))//单身狗或拆原配            {                match[v] = u;                return true;            }        }    }    return false;}int Hungary(int n){    int ans = 0;    memset(match, -1, sizeof(match));    for(int i = 0; i < n; i++)    {        memset(vis, false, sizeof(vis));        if(Augment(n, i)) ans++;    }    return ans;}int main(){  //  freopen("in.txt", "r", stdin);    int n, m, u, v;    while(~scanf("%d", &n))    {        init();        for(int i = 0; i < n; i++)        {            scanf("%d:(%d)", &u, &m);            while(m--)            {                scanf("%d", &v);                add(u, v);            }        }        printf("%d\n", Hungary(n)/2);    }    return 0;}


0 0