HDU 1054 Strategic Game (最小顶点覆盖)

刚开始想得难了,打算把二分图建出来,把顶点分开!其实不用,直接对原图求最大匹配,然后除以2.

这里刚开始敲模板,把下标弄错了,题目是从0开始,我直接从1开始!还有一件事情,一定一定要记得,就是给bmap初始化!!!!很重要,至关重要的!!!

代码:

#include <cstdio>
#include <cstring>
#include <queue>
using namespace std;

const int N = 1515;
const int INF = 0x3fffffff;
int n, bmap[N][N], cy[N], cx[N];
int dy[N], dx[N], dis;
bool used[N];

bool search()
{
    queue <int> Q;
    dis = INF;
    memset(dx, -1, sizeof(dx));
    memset(dy, -1, sizeof(dy));
    for ( int i = 0; i < n; ++i )
        if ( cx[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 < n; ++v )
            if ( bmap[u][v] && dy[v] == -1 ) {
                dy[v] = dx[u] + 1;
                if ( cy[v] == -1 ) dis = dy[v];
                else {
                    dx[cy[v]] = dy[v]+1;
                    Q.push( cy[v] );
                }
            }
    }
    return dis != INF;
}
bool dfs( int u ) 
{
    for ( int v = 0; v < n; ++v ) if ( bmap[u][v] && !used[v] && dx[u]+1 == dy[v] ) {
        used[v] = 1;
        if ( cy[v] != -1 && dy[v] == dis ) continue;
        if ( cy[v] == -1 || dfs( cy[v] ) ) {
            cy[v] = u;
            cx[u] = v;
            return 1;
        }
    }
    return 0;
}
int Hmatch()
{
    int res = 0;
    memset(cy, -1, sizeof(cy));
    memset(cx, -1, sizeof(cx));
    while ( search() ) {
        memset( used, 0, sizeof(used));
        for ( int i = 0; i < n; ++i ) if ( cx[i] == -1 ) {
            res += dfs(i);
        }
    }
    return res;
}
int main()
{
    while ( scanf("%d", &n) != EOF ) {
        memset(bmap, 0, sizeof(bmap));
        for ( int i = 0; i < n; ++i ) {
            int u, v, k;
            scanf("%d:(%d)", &u, &k);
            while( k-- ) {
                scanf("%d", &v);
                bmap[u][v] = bmap[v][u] = 1;
            }
        }
        printf("%d\n", Hmatch()/2);
    }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值