补图

补图

Time Limit: 1000 ms Memory Limit: 65536 KiB

Submit Statistic

Problem Description

题目给出一个无向图,求该无向图关于完全图的相对补图,并求该补图的最大度和最小度。方便起见,用邻接矩阵表示该无向图。无向图的节点数不少于2并且不超过500.

Input

多组输入,每组输入第一行是无向图中节点的数量即邻接矩阵的行列数n。接下来n行n列为该图的邻接矩阵。

Output

每组数据,首先输出n行n列表示补图的邻接矩阵。接下来一行两个用空格分隔的整数,分别代表补图的最大度和最小度。

Sample Input

4
0 0 1 1
0 0 0 1
1 0 0 0
1 1 0 0

Sample Output

0 1 0 0
1 0 1 0
0 1 0 1
0 0 1 0
2 1

Hint

Source

一步踏尘千劫累

本题是利用矩阵求补图,思路就是先建立一个同a数组相同的数组b,然后对b进行处理。将b数组的对角线元素抛去,看其他的元素,如果在原矩阵a中元素是1,那么在b中对应的就是0.同理a[i][j]=0,b[i][j]=1。相反着来就可以。然后建立两个变量用来求最大度和最小度。一个二重循环下进行数组的遍历即可,用一个变量t来存放每一行的度,之后再与之前的最大最小进行比较交换即可。

AC代码:

#include<bits/stdc++.h>
using namespace std;
int a[600][600],b[600][600];
int main()
{
	int n;
	while(~scanf("%d",&n))
	{
		memset(a,0,sizeof(a));
		memset(b,0,sizeof(b));
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				scanf("%d",&a[i][j]);
				b[i][j]=a[i][j];
			}
		}
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				if(i!=j&&a[i][j]==1)
				{
					b[i][j]=0;
				}
				else if(i!=j&&a[i][j]==0)
				{
					b[i][j]=1;
				}
			}
		}
		int t=0;
		int max=0,min=600;
		for(int i=1;i<=n;i++)
		{
			t=0;
			for(int j=1;j<=n;j++)
			{
				if(b[i][j]==1)
				{
					t++;
				}
			}
			if(max<=t)
			{
				max=t;
			}
			if(min>=t)
			{
				min=t;
			}
		}
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=n;j++)
			{
				if(j==n)
				{
					printf("%d\n",b[i][j]);
				}
				else
				{
					printf("%d ",b[i][j]);
				}
			}
		}
		printf("%d %d\n",max,min);
	}
	return 0;
 } 

 

### 关于补图的定义与性质 在图论中,给定一个简单无向图 \( G(V,E) \),其补图 \( \overline{G}(V,\overline{E}) \) 是指具有相同顶点集 \( V \),但边集 \( \overline{E} \) 中仅包含那些不在原图 \( E \) 中的边。换句话说,如果两个节点 \( u,v \in V \) 在 \( G \) 中不相连,则它们在 \( \overline{G} \) 中必然相连。 以下是补图的一些重要特性: - 原图和补图的边集合互斥且覆盖所有可能的边组合[^1]。 - 如果原图为完全图,则其补图为空图;反之亦然。 --- ### 补图算法的具体实现 #### 使用 NetworkX 实现补图计算 `NetworkX` 提供了一个内置函数 `complement(G)` 来快速生成任意图的补图。下面是一个完整的 Python 示例: ```python import networkx as nx import matplotlib.pyplot as plt # 创建原始图 G G = nx.Graph() edges = [(1, 2), (2, 3), (3, 4)] G.add_edges_from(edges) # 计算补图 G_complement = nx.complement(G) # 可视化原图和补图 plt.figure(figsize=(10, 5)) plt.subplot(1, 2, 1) nx.draw(G, with_labels=True, node_color='lightblue', edge_color='gray') plt.title("Original Graph") plt.subplot(1, 2, 2) nx.draw(G_complement, with_labels=True, node_color='lightgreen', edge_color='red') plt.title("Complement Graph") plt.show() ``` 上述代码展示了如何创建一个简单的无向图及其对应的补图,并通过可视化方式呈现两者的关系。 #### 手动实现补图算法 如果不借助第三方库,可以手动构建补图如下所示: ```python def generate_complement_graph(graph): """ 输入:graph - 字典形式表示的邻接表 {node: [neighbors]} 输出:complement_graph - 邻接表形式的补图 """ nodes = list(graph.keys()) complement_graph = {node: [] for node in nodes} n = len(nodes) all_pairs = set((nodes[i], nodes[j]) for i in range(n) for j in range(i + 1, n)) existing_edges = set() for u, neighbors in graph.items(): for v in neighbors: if u < v: existing_edges.add((u, v)) else: existing_edges.add((v, u)) missing_edges = all_pairs - existing_edges for u, v in missing_edges: complement_graph[u].append(v) complement_graph[v].append(u) return complement_graph # 测试用例 original_graph = { 1: [2], 2: [1, 3], 3: [2, 4], 4: [3] } complement_graph = generate_complement_graph(original_graph) print(complement_graph) ``` 此代码片段实现了从邻接表形式的输入图生成其补图的功能[^3]。 --- ### 判断两图是否为彼此的补图 为了验证两张图是否互为补图,需满足以下条件: 1. 它们的顶点集完全一致; 2. 对于任一顶点对 \( (u,v) \),要么属于其中一个图的边集,要么属于另一个图的边集,二者必居其一。 可以通过以下伪代码描述该过程: ```plaintext function is_complement(G1, G2): if vertices(G1) != vertices(G2): return False edges_union = union(edges(G1), edges(G2)) possible_edges = {(i,j) | ∀ i ≠ j ∈ vertices(G1)} return edges_union == possible_edges and intersection(edges(G1), edges(G2)) == ∅ ``` 实际编码时可参考以下 Python 版本: ```python def are_complements(graph1, graph2): """判断两个图是否互为补图""" # 检查顶点集一致性 if set(graph1.keys()) != set(graph2.keys()): return False # 构造全连接图的所有可能边 nodes = list(graph1.keys()) all_possible_edges = set( tuple(sorted([nodes[i], nodes[j]])) for i in range(len(nodes)) for j in range(i + 1, len(nodes)) ) # 获取两个图的实际边集 def get_edges(g): edges_set = set() for u, neighbors in g.items(): for v in neighbors: edges_set.add(tuple(sorted([u, v]))) return edges_set edges_g1 = get_edges(graph1) edges_g2 = get_edges(graph2) # 边集应互补且覆盖全部可能性 return edges_g1.union(edges_g2) == all_possible_edges and not (edges_g1.intersection(edges_g2)) ``` --- ### 性能优化考虑 对于大规模稀疏图,直接枚举所有可能边可能导致性能瓶颈。因此,在实际应用中建议先估算所需存储空间以及时间复杂度后再决定是否采用暴力法或更高效的启发式策略。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值