Jurassic Jigsaw
Kattis - jurassicjigsaw (最小生成树)
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 Sample Output 1
4 2
AA
AT
TT
TC
3
0 1
1 2
2 3
Sample Input 2 Sample Output 2
4 1
A
A
G
T
2
0 1
0 2
0 3
Sample Input 3 Sample Output 3
5 6
GAACAG
AAAAAA
AACATA
GAAAAG
ATAAAT
7
0 3
1 2
1 3
1 4
题目大意:给你一些基因,知道基因之间的变异难度,让你求这些基因的进化树(进化难度尽量最小)
这道题就是一个最小生成树的题,我们把每个基因看作节点,把进化难度看作边权即可。需要注意的是,每两个之间都有可能进化,也就是存图的时候会有(n*(n-1))/2种情况,本来稠密图的话用普里姆算法比较好,但是这道题需要输出所有的边(无顺序),那就只能用克鲁斯卡尔了,但是当时我真的担心过不了啊
本题在一般的克鲁斯卡尔上又加了加边操作,但是没有难多少
#include <iostream>
#include <bits/stdc++.h>
using namespace std;
struct node
{
int x, y;
int len;
} a[1000100];
int tot=0;
int n, k;
bool cmp(node a, node b)
{
return a.len<b.len;
}
int pre[1005];
int findd(int x)
{
while(x!=pre[x])
x=pre[x];
return x;
}
void gui(int x, int y)
{
if(findd(x)!=findd(y))
pre[findd(x)]=findd(y);
}
void prework()
{
for(int i=0;i<=n;i++)
{
pre[i] = i;
}
}
char ch[1110][20];
void input()
{
for(int i = 0; i<n; i++)
{
scanf("%s",ch[i]);
for(int j = 0; j<i; j++)
{
int sum = 0;
for(int h = 0; h<k; h++)
{
if(ch[i][h]!=ch[j][h])
sum++;
}
a[++tot].x = i;
a[tot].y = j;
a[tot].len = sum;
}
}
}
int main()
{
scanf("%d %d", &n, &k);
prework();
input();
sort(a+1,a+1+tot,cmp);
int cou = 0;
int ans = 0;
queue<pair<int,int> >path;
for(int i = 1; i<=tot&&cou<n-1; i++)
{
if(findd(a[i].x)!=findd(a[i].y))
{
gui(a[i].x,a[i].y);
path.push(make_pair(a[i].y,a[i].x));
ans+=a[i].len;
cou++;
}
}
printf("%d\n",ans);
while(!path.empty())
{
pair<int,int>t;
t = path.front();
path.pop();
printf("%d %d\n",t.first,t.second);
}
return 0;
}
还用了些stl的内容,其实不用一样能做,只不过保存了下答案