poj-2594

31 篇文章 0 订阅
17 篇文章 0 订阅
// 2712K   266MS   G++ 
#include <cstdio>
#include <cstring>
#include <queue>

using namespace std;
#define MAX 520

int G[MAX][MAX];
int G_F[MAX][MAX];

int iNum;
int sNum;

int V1[MAX];
int V2[MAX];
char waitingMove[MAX];

queue<int> BFSQueue;

char getPair(int checkId) {
    for (int i = 1; i <= iNum; i++) {
        if (G_F[checkId][i]) { // if checkId connect i
            if (!V2[i]) { // if not assigned
                V1[checkId] = i;
                V2[i] = checkId;
                return 1;
            } else {
                if (!waitingMove[V2[i]]) { // if i's owner is not waiting move
                    waitingMove[V2[i]] = 1; // try to move i's owner
                    if (getPair(V2[i])) { // move i's owner success
                        V1[checkId] = i;
                        V2[i] = checkId;
                        return 1;
                    }
                }
            }
        }
    }
    return 0;
}

char BFSFlag[MAX]; // 0 no check / 1 found / 2 checked

void checkConnectibity(int checkId) {
    memset(BFSFlag, 0, sizeof(BFSFlag));
    while(BFSQueue.size()) {
        BFSQueue.pop();
    }

    BFSQueue.push(checkId);
    BFSFlag[checkId] = 1;
    while(BFSQueue.size()) {
        int curId = BFSQueue.front(); // get current checking node
        BFSQueue.pop();
        if (curId != checkId) {
            G_F[checkId][curId] = 1;
        }
        for (int i = 1; i <= iNum; i++) { // check adjancey node
            if (G[curId][i]) { // if connected
                if (!BFSFlag[i]) { // if first found
                    BFSFlag[i] = 1;
                    BFSQueue.push(i);
                }
                
            }
        }
        BFSFlag[curId] = 2;
    }

}

void solve() {
    memcpy(G_F, G, sizeof(G));
    for (int i = 1; i <= iNum; i++) {
        checkConnectibity(i);
    }

    int maxMatchNum = 0;

    for (int i = 1; i <= iNum; i++) {
        memset(waitingMove, 0, sizeof(waitingMove));
        if (getPair(i)) {
            maxMatchNum++;
        }
    }
    printf("%d\n", iNum - maxMatchNum);
}

int main() {
    int caseNum;
    // scanf("%d", &caseNum);
    // for (int i = 0; i<caseNum; i++) {
    while(1) {
        memset(G, 0, sizeof(G));
        memset(V1, 0, sizeof(V1));
        memset(V2, 0, sizeof(V2));
        scanf("%d %d", &iNum, &sNum);
        if (iNum == 0 && sNum ==0) {
            return 0;
        }
        for (int i = 0; i < sNum; i++) {
            int iBegin;
            int iEnd;
            scanf("%d %d", &iBegin, &iEnd);
            G[iBegin][iEnd] = 1;
        }
        solve();
    }
}

和1422简直一模一样,除了一个关键的区别:1422的路径之间不能相交,直接符合最小路径覆盖,

而2594 则允许了路径覆盖,这样就不能直接用最小路径覆盖解了,e.g

5个点 1->2->3, 4->2->5, 如果按照最小路径覆盖,那么会最少需要3个robot遍遍历所有点(4 和 5被2隔开,但是2被1->2->3所覆盖,因此不能有4->2->5这个路径)

但是如果允许路径相交,那么只需要2个robot: 1->2->3  4->2->5即可。

这样,问题就变成了如何将这个允许相交转化,

注意到,4->5是相通的,如果按照最小路径覆盖,而且4到5是直达的话,那么最小路径覆盖的结果是正确的,

因此,要对点的连接关系做这样的预处理:以前只标示两个点是否直接可达,现在则标示两个点 是否 可达(中间可能会有多个点)。

这样,就绕过了相交点的影响,“飞”过了一样(4->2->5, 现在直接4->5).至于如何求可达,直接BFS/DFS每个点i即可,在图遍历中遇到的点j都是从i可达的

尝试进行了优化,及在遍历到某个点k时,如果点k的可达性测试之前完成了,那么对于k联通的点M,可以直接视为i也可达m(i->k->M 等价于 i->M),这样点k就不必在进入BFS

队列来增加运算,但是结果反而不理想,优化前200多ms,优化后438ms.....

上面的 飞过某个点 是个trick,要牢记。

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值