天津 2010 I'm telling the truth

本文介绍了一个使用最大匹配算法解决特定问题的实现方案。通过从后往前遍历输入数据,找到最大的匹配序列,并详细展示了如何利用C++编程语言来具体实现这一算法过程。

最大匹配。

从后往前匹配就可以知道最大的序列。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <string>
#include <iostream>

#define MaxN 100005
#define MaxS 65

using namespace std;

bool checked[MaxN];
int x[MaxS];
int y[MaxN];
int stu;
int max_rank, min_rank;
bool map[MaxS][MaxN];

bool search(int i)
{
    for(int j = min_rank; j <= max_rank; j++) {
        if(!checked[j] && map[i][j]) {
            checked[j] = true;
            if(y[j] == -1 || search(y[j])) {
                x[i] = j;
                y[j] = i;
                return true;
            }
        }
    }
    
    return false;
}
        
int getMatch()
{
    int match = 0;
    for(int i = 1; i <= stu; i++)
        x[i] = -1;
    for(int j = min_rank; j <= max_rank; j++)
        y[j] = -1;
    for(int i = stu; i >= 1; i--) {
        if(x[i] == -1) {
            memset(checked, false, sizeof(checked));
            if(search(i))
                match++;
        }
    }
    
    return match;
}

int main()
{
    int t;
    while(scanf("%d", &t) != EOF) {
        while(t--) {
            scanf("%d", &stu);
            
            max_rank = 0;
            min_rank = MaxN;
            memset(map, false, sizeof(map));
            
            for(int i = 1; i <= stu; i++) {
                int a, b;
                scanf("%d%d", &a, &b);
                max_rank = max(max_rank, max(a, b));
                min_rank = min(min_rank, min(a, b));
                for(int j = a; j <= b; j++)
                    map[i][j] = true;
            }
            int res = getMatch();
            
            printf("%d\n", res);
            int count = 0;
            for(int i = 1; i <= stu; i++) {
                if(x[i] != -1) {
                    count++;
                    if(count < res)
                        printf("%d ", i);
                    else
                        printf("%d\n", i);
                }
            }
        }
    }
    return 0;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值