zzuli 1918(匹配 宝塔开门)

Description

晴天也来寻宝啦,有一个m层的宝塔,只能从第一层开始一层一层的往上走,每层都有一个门,你需要用钥匙来打开门才能继续走,现在晴天有n把钥匙,编号为0-n-1,然后他要开始寻宝了。没有特殊技能怎么好意思出来寻宝呢,他现在有两个天赋技能,他知道第i层的门可以用编号为a和b的钥匙打开(可能a等于b呦),然后他还可以在进入宝塔前把门的顺序任意调换一次,也就是说比如可以把m层原来的1 2 3 ..m,换为 m ...3 2 1.晴天想知道他最多能拿到多少层的宝物。

Input

第一行一个整数t表示有多少组测试实例

每组数据第一行为两个整数n,m分别表示有多少个钥匙,有多少层。

接下来m行,每行两个数字x,y,第i行表示第i层的门可以用标号x或y的钥匙打开。

(n,m<=1000)

Output

输出一个整数表示最多可以上多少层。

Sample Input

1 3 4 0 1 0 1 0 1 1 2

Sample Output

3

HINT

在样例中,在进入宝塔前,将门的顺序换为4 1 2 3.然后前三层分别使用2 0 1三把钥匙拿到前三层的宝物

题目大意:有编号0~n-1共n把钥匙,有m层宝塔,每层可通过两把钥匙中任一把(用后报废),宝塔层数顺序无视,问可开几层塔。

最近打练习赛发现几道匹配题,结果自己赛中根本没发现是匹配题,匹配还是太弱,这里写篇博,巩固一下。

#include <iostream>
#include<stdio.h>
#include<queue>
#include<string.h>
#include<ctype.h>
#include<math.h>
#include<vector>
#include<algorithm>
#include<stack>
using namespace std;
#define oo 0x3f3f3f3f
#define maxn 1010

int G[maxn][maxn];//钥匙层数间是否可匹配
int used[maxn];//该钥匙是否已匹配
int vis[maxn];//标记钥匙是否用过
int n,m;

bool pipei(int u)//核心匹配函数
{
    for(int i=0;i<n;i++)
    {
        if(!vis[i]&&G[u][i])
        {
            vis[i]=1;//该钥匙消耗
            if(!used[i]||pipei(used[i]))//该钥匙可用或该钥匙曾匹配的层可匹配其他钥匙让出该钥匙
            {
                used[i]=u;//编号i的钥匙被u层消耗
                return true;
            }
        }
    }
    return false;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        scanf("%d%d",&n,&m);
        memset(G,0,sizeof(G));
        for(int i=1;i<=m;i++)
        {
            int x,y;
            scanf("%d%d",&x,&y);
            if(x<n&&x>=0)
                G[i][x]=1;
            if(y<n&&y>=0)
                G[i][y]=1;//i层可被x、y钥匙打开
        }

        memset(used,0,sizeof(used));//初始化钥匙匹配状态
        int ans=0;
        for(int i=1;i<=m;i++)
        {
            memset(vis,0,sizeof(vis));//初始化钥匙存在状态
            if(pipei(i))
                ans++;
        }
        printf("%d
",ans);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/zz1164056454/p/5782950.html