19PAT模拟赛(4)图的 极大匹配

本文介绍了一种算法,用于判断给定的边集是否构成无向图的极大匹配。极大匹配是指在匹配的基础上,无法通过添加图中剩余的边来扩大匹配规模。文章详细解释了匹配和极大匹配的概念,并提供了一个示例输入输出及代码实现。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Case Time Limit: 500 MS (Others) / 1000 MS (Java) Case Memory Limit: 256 MB (Others) / 512 MB (Java)
Accepted: 115 Total Submission: 334

查看我的提交
Problem Description
对给定的无向图G=(V,E),如果边集E’满足:(1)E’是E的子集;(2)E’中的任意两条边都没有公共顶点,那么称边集E’为图G的一个匹配(Matching)。而如果往E’中增加任意一条在E中但不在E’中的边,都会导致E’不再是图G的匹配,那么称E’为图G的一个极大匹配(Maximal Matching)。
(以上定义引自https://en.wikipedia.org/wiki/Matching_(graph_theory))

根据上面的定义,请判断一些给定的边集是否是给定的无向图的极大匹配。

Input
每个输入文件一组数据。

第一行两个整数N、M(1<=N<=1000, 0<=M<=N*(N-1)/2),表示顶点数和边数,假设所有顶点的编号为1到N。

接下来M行,每行两个正整数u、v(1<=u,v<=N, u!=v),表示一条边的两个端点编号。

然后一个正整数K(K<=10),表示查询个数。

接下来为K个查询,每个查询第一行为一个正整数L,表示待查询边集的边数,接下来L行每行两个正整数,表示一条边的两个端点编号。数据保证每个查询中相同的边只会出现一次,且所有边都在图中存在。

Output
每个查询输出一行,如果给定的边集是极大匹配,那么输出Yes;如果它是匹配但不是极大匹配,那么输出Not Maximal;如果不是匹配,那么输出Not a Matching。

Sample Input
4 4
1 2
1 3
2 3
2 4
4
1
2 3
1
1 3
2
1 2
2 4
2
1 3
2 4
Sample Output
Yes
Not Maximal
Not a Matching
Yes

#include <stdio.h>
#include<iostream>
#include <string.h>
#include <string>
#include <algorithm>
#include <map>
using namespace std;
#include <set>
const int MAXV = 1010;  // 顶点数上限
int G[MAXV][MAXV] = { {0} };     // 无向图G
int G1[MAXV][MAXV] = { { 0 } };
bool vis[MAXV];         // 顶点是否已被访问
int n, m, L;   // 顶点数, 边数, 被删除的顶点编号
set<int> se;
bool flag=true;
bool isMaximal(int G1[MAXV][MAXV])
{
	int len = se.size();
	int num;
	for (int i = 1; i <= n; i++)
		for (int j = 1; j <= n; j++)
		{
			if (G1[i][j] == 1)
			{
				se.insert(i);
				int len1 = se.size();
				se.insert(j);
				int len2 = se.size();
				if (len2 != len + 2)
				{
					if (len1 == len + 1)
						se.erase(i);
					if (len2 == len1 + 1)
						se.erase(j);
				}	
				else
					return false;
			}
		}
	return true;
}
int main() {
	scanf("%d%d", &n, &m);  // 顶点数, 边数
	for (int i = 0; i < m; i++) {
		int u, v;
		scanf("%d%d", &u, &v);
		G[u][v] = G[v][u] = 1;   // 无向图的边
	}
	int k;
	scanf("%d", &k);    // 查询个数
	while (k--) {
		se.clear();
		flag = true;
		for (int i = 1; i <= n; i++)
			for (int j = 1; j <= n; j++)
				G1[i][j] = G[i][j];
		scanf("%d", &L);   
		for (int i = 0; i < L; i++)
		{
			int u, v;
			scanf("%d%d", &u, &v);
			G1[u][v] = G1[v][u] = 2;
			int len = se.size();
			se.insert(u);
			se.insert(v);
			if (se.size() < len + 2)
			{
				printf("Not a Matching\n");
				flag = false;
				break;
			}
		}
		if (flag)
		{
			if (isMaximal(G1))
				printf("Yes\n");
			else
				printf("Not Maximal\n");
		}
		
	}
	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值