洛谷P2071 座位安排

题目背景

公元二零一四年四月十七日,小明参加了省赛,在一路上,他遇到了许多问题,请你帮他解决。

题目描述

已知车上有N排座位,有N*2个人参加省赛,每排座位只能坐两人,且每个人都有自己想坐的排数,问最多使多少人坐到自己想坐的位置。

输入格式

第一行,一个正整数N。

第二行至第N*2+1行,每行两个正整数Si1,Si2,为每个人想坐的排数。

输出格式

一个非负整数,为最多使得多少人满意。

题解:显然可以点可以分为两个集合,左集合是人,右集合是座位,把每一列座位拆成两个点,然后想让最多人满意,

就把当前人和他满意的排数的两个点连一条边,跑一个二分图最大匹配即可。

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

using namespace std;

struct node
{
    int ed,nxt;
};
node edge[4005*16];
int n,cnt,first[4005],ans;
bool used[4005*2];
int match[4005*2];

inline void add_edge(int s,int e)
{
    cnt++;
    edge[cnt].ed=e;
    edge[cnt].nxt=first[s];
    first[s]=cnt;
    return;
}

inline bool dfs(int k)
{
    for(int i=first[k];i;i=edge[i].nxt)
    {
        int ed=edge[i].ed;
        if(!used[ed]) 
        {
            used[ed]=true;
            if(!match[ed]||dfs(match[ed]))
            {
                match[ed]=k;
                return true;
            }
        }
    }
    return false;
}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=2*n;i++)
    {
        int s1,s2;
        scanf("%d%d",&s1,&s2);
        add_edge(i,s1*2-1); add_edge(i,s1*2);
        add_edge(i,s2*2-1); add_edge(i,s2*2);
    }
    for(int i=1;i<=2*n;i++)
    {
        memset(used,false,sizeof(used));
        if(dfs(i)) ans++;
    }
    printf("%d",ans);
    return 0;
}
原文地址:https://www.cnblogs.com/Hoyoak/p/11422902.html