Training Contest 5 - J - Jurassic Jigsaw

题目
The famous Jurassic park biologist Dean O’Saur has discovered new samples of what he expects to be the DNA of a dinosaur. With the help of his assistant Petra Dactil, he managed to sequence the samples, and now they are ready for analysis. Dean thinks this dinosaur was affected with a particular disease that mutated the DNA of some cells.

To verify his theory, he needs to compute the most likely evolutionary tree from the samples, where the nodes are the samples of DNA. Because there is no temporal data for the DNA samples, he is not concerned where the root of the tree is.

Dean considers the most likely evolutionary tree, the tree with smallest unlikeliness: the unlikeliness of a tree is defined as the sum of the weights of all edges, where the weight of an edge is the number of positions at which the two DNA strings are different.

As a world expert in data trees, he asks you to reconstruct the most likely evolutionary tree.

In the first sample, the optimal tree is AA - AT - TT - TC . The unlikeliness of the edge between AA and AT edge is 1, because the strings AA and AT differ in exactly 1 position. The weights of the other two edges are also 1, so that the unlikeliness of the entire tree is 3. Since there is no tree of unlikeliness less than 3, the minimal unlikeliness of an evolutionary tree for this case is 3.

Input
The first line consists of two integers 1≤n≤1000 and 1≤k≤10, the number of samples and the length of each sample respectively.

Each of the next n lines contains a string of length k consisting of the characters in ACTG.

Output
On the first line, print the minimal unlikeliness of the evolutionary tree.

Then, print n−1 lines, each consisting of two integers 0≤u,v<n, indicating that in the most likely evolutionary tree, there is an edge between DNA string u and v. If there are multiple answers possible, any of them will be accepted.

Sample Input 1
4 2
AA
AT
TT
TC
Sample Output 1
3
0 1
1 2
2 3
Sample Input 2
4 1
A
A
G
T
Sample Output 2
2
0 1
0 2
0 3
Sample Input 3
5 6
GAACAG
AAAAAA
AACATA
GAAAAG
ATAAAT
Sample Output 3
7
0 3
1 2
1 3
1 4

题目讲了很多,实际上理解了就很简单,就是让你求一个图的最小生成树,而两个节点间的权值就是这两个节点表示的字符串之间相同位置字母不同的位置的总个数,用Kruskal算法解决

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<queue>
using namespace std;
char s[1005][15];
int parent[1005];
int b=0,n,k;
struct node
{
	int u,v,w;        //第i条边两端点序号和权值
	friend bool operator < (const node a,const node b){  //修改重载运算符
		return a.w>b.w;
	}
};
priority_queue<node> que;
queue<int> q;       //存生成的最小生成树的边两端的节点 
int root(int x)
{
	return parent[x]==x?x:parent[x]=root(parent[x]);
}
void merge(int x,int y)
{
	int f1=root(x);
	int f2=root(y);
	if(f1!=f2){
		parent[f2]=f1;
	}
}
int kruskal()
{
	int ans=0;
	for(int i=0;i<n;i++) parent[i]=i;
	while(!que.empty()){
		node tmp=que.top();que.pop();
		if(root(tmp.u)==root(tmp.v)) continue;
		ans+=tmp.w;
		merge(tmp.u,tmp.v);
		q.push(tmp.u);
		q.push(tmp.v);
	}
	return ans;
}
int main()
{
	cin>>n>>k;
	for(int i=0;i<n;i++){
		scanf("%s",&s[i]);
	}
	node temp;
	for(int i=0;i<n;i++){
		for(int j=i+1;j<n;j++){
			int c=0;
			for(int d=0;d<k;d++){
				if(s[i][d]!=s[j][d])
					c++;
			}
			temp.u=i;
			temp.v=j;
			temp.w=c;
			que.push(temp);
		}
	}
	int sum=kruskal();
	cout<<sum<<endl;
	while(!q.empty()){
		cout<<q.front();q.pop();
		cout<<" "<<q.front()<<endl;q.pop();
	}
	return 0;
}
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值