HDU 3729【二分匹配】

题意:
给出n个同学的排名,代表每个排名在哪个区间,要求保证最多人说的是实话,并在此前提下求一个说真话人最大字典序。
思路:
最后感觉就是点去填区间,点和区间建个边,然后跑个二分图,然后sort一发。

#include<cstdio>
#include<vector>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;

const int N=1e5+10;

struct asd{
    int to;
    int next;
};
asd q[N*65];
int head[N*65];
int cy[N];
int n,tol;
bool vis[N];

vector<int>pp;
void add(int a,int b)
{
    q[tol].to=b;
    q[tol].next=head[a];
    head[a]=tol++;
}
int findpath(int u)
{
    for(int k=head[u];k!=-1;k=q[k].next)
    {
        int i=q[k].to;
        if(vis[i])
            continue;
        vis[i]=1;
        if(cy[i]==-1||findpath(cy[i]))
        {
            cy[i]=u;
            return 1;
        }
    }
    return 0;
}
int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int x,y;
        int k;
        scanf("%d",&n);
        memset(head,-1,sizeof(head));
        tol=0;
        for(int i=1;i<=n;i++)
        {
            scanf("%d%d",&x,&y);
            if(x>y)
                swap(x,y);
            for(int j=x;j<=y;j++)
            {
                add(i,j);
                //add(j,i);
            }
        }
        int ans=0;
        pp.clear();
        memset(cy,-1,sizeof(cy));
        for(int i=n;i>=1;i--)
        {
            memset(vis,0,sizeof(vis));
            if(findpath(i))
            {
                ans++;
            }
        }
        for(int i=1;i<=100000;i++)
        {
            if(cy[i]!=-1)
                pp.push_back(cy[i]);
        }
        sort(pp.begin(),pp.end());
        printf("%d\n",ans);
        for(int i=0;i<pp.size();i++)
        {
            if(i) printf(" ");
            printf("%d",pp[i]);
        }
        puts("");
    }
    return 0;
}
posted @ 2016-09-29 00:23  see_you_later  阅读(130)  评论(0编辑  收藏  举报