列表

详情


NC20807. 生成树

描述

你有一张n个点的完全图(即任意两点之间都有无向边)
现在给出这张图的两棵生成树
定义一次操作为:在任意一棵生成树中删除一条边后再加入一条边(必须在同一棵树中操作),同时需要保证操作完后仍然是一棵树
问使得两棵树相同的最少操作次数,若不存在合法的操作方案,输出-1

注意:这里的相同指的是点集与边集均相同,也就是对于第一棵树中的边(u, v),第二棵树中一定存在边(u, v)或(v, u),再不懂请看样例解释。

输入描述

一个整数n表示无向图的点数
接下来n - 1行,每行两个整数u, v表示第一棵生成树中的边
再接下来n - 1行,每行两个整数u, v表示第二棵生成树中的边

输出描述

一个整数,表示最少操作次数

示例1

输入:

6
6 1
1 2
2 3
3 5
5 4
1 2
2 4
4 5
5 3
6 4

输出:

2

说明:

题目中的树如下所示
一种方案如下:
第二棵树中删除(2, 4),增加(2,3)
第二棵树中删除(4, 6),增加(1, 6)
注意:如果仅在第二棵树中删除(2, 4),增加(1, 6),得到的树虽然形态相同,但是边集不同,我们不认为它们是相同的!

示例2

输入:

3
1 2
2 3
1 3
3 2

输出:

1

示例3

输入:

2
1 2
2 1

输出:

0

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

Python3(3.5.2) 解法, 执行用时: 826ms, 内存消耗: 24028K, 提交时间: 2018-11-01 21:17:22

n=int(input(""))
ans=0;
mp={}
for i in range(n-1):
    x,y=map(int,input().split())
    if x>y:
        x,y=y,x
    mp[(x,y)]=1
for i in range(n-1):
    x,y=map(int,input().split())
    if x>y:
        x,y=y,x
    if not(mp.get((x,y))):
        ans+=1
print(ans);

C 解法, 执行用时: 55ms, 内存消耗: 800K, 提交时间: 2022-03-20 14:21:41

#include<stdio.h>
int main(){
	int tree[100010],ans=0;
	int n,u,v;
	scanf("%d",&n);
	for(int i=0;i<n-1;i++){
	scanf("%d%d",&u,&v);
	tree[u]=v;
	}
	for(int i=0;i<n-1;i++){
	scanf("%d%d",&u,&v);
	if(tree[u]==v||tree[v]==u){
		ans++;
	}
	}
	printf("%d\n",n-1-ans);
}

pypy3 解法, 执行用时: 602ms, 内存消耗: 37416K, 提交时间: 2022-04-16 21:41:58

n = int(input())
ans = 0
mp={}
for i in range(n-1):
    x,y=map(int,input().split())
    x,y = min(x,y),max(x,y)
    mp[(x,y)]=1
for i in range(n-1):
    x,y=map(int,input().split())
    x,y = min(x,y),max(x,y)
    if not(mp.get((x,y))):
        ans+=1
print(ans)

C++11(clang++ 3.9) 解法, 执行用时: 105ms, 内存消耗: 836K, 提交时间: 2020-07-28 19:48:42

#include<bits/stdc++.h>
using namespace std;
int a[100005];
int main()
{
	int n,x,y,s=0;
	cin>>n;
	for(int i=0;i<n-1;i++)
	{
		cin>>x>>y;
		a[x]=y;
	}
	for(int i=0;i<n-1;i++)
	{
		cin>>x>>y;
		if(a[x]!=y&&a[y]!=x) s++;
	}
	cout<<s;
	return 0;
}

上一题