HDU--3729(建模*,最大匹配)

2015-06-08 15:29:15

题目:n个人参加了一次考试,每个人都有一个排名(1~n),且排名间互不相同。每个人给出一个他的排名所在的区间,(比如 [2,10] 表示他的排名在2~10之间)

  但是每个人都可能撒谎,问最多可能有多少人说了真话。(n <= 60 , 区间的左右端点 <= 1e6)

思路:一个开始根本没啥思路,后来看了题解... 发现自己的思维实在太烂了... 

  正解是二分图最大匹配,因为每个排名值的独立的(即可以作为一个人的排名),所以对于每个人的区间 [L,R],L~R里的每个值都可以和这个人匹配,所以建边

  然后其实就是求一个最大匹配了。

#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <cmath>
#include <vector>
#include <map>
#include <set>
#include <stack>
#include <queue>
#include <string>
#include <iostream>
#include <algorithm>
using namespace std;

#define getmid(l,r) ((l) + ((r) - (l)) / 2)
#define MP(a,b) make_pair(a,b)
#define PB(a) push_back(a)

typedef long long ll;
typedef pair<int,int> pii;
const double eps = 1e-8;
const int INF = (1 << 30) - 1;
const int MAXN = 70;

int T,n,num[100010],cnt;
int mat[100010],used[100010];
struct node{
    int x,y;
}P[MAXN];

bool find(int p){
    for(int i = P[p].x; i <= P[p].y; ++i){
        if(used[i] == 0){
            used[i] = 1;
            if(mat[i] == 0 || find(mat[i])){
                mat[i] = p;
                num[p] = 1;
                return true;
            }
        }
    }
    return false;
}

int Hungary(){
    int ans = 0;
    memset(num,0,sizeof(num));
    memset(mat,0,sizeof(mat));
    for(int i = n; i >= 1; --i){
        memset(used,0,sizeof(used));
        if(find(i)){
            ++ans;
        }
    }
    return ans;
}

int main(){
    scanf("%d",&T);
    while(T--){
        scanf("%d",&n);
        for(int i = 1; i <= n; ++i){
            scanf("%d%d",&P[i].x,&P[i].y);
        }
        printf("%d\n",Hungary());
        for(int i = 1; i <= n; ++i) if(num[i]){
            printf("%d%c",i,(i == n) ? '\n' : ' ');
        }
    }
    return 0;
}

 

posted @ 2015-06-08 23:41  Naturain  阅读(108)  评论(0编辑  收藏  举报