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; }