题目链接:http://uva.onlinejudge.org/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=4170
题意:
对于一个连通无向图,给定一个有n个节点的序列A,找到具有相同节点的序列B(保证联通),求出最小的两个序列的距离,
距离的求法:
dist(A, B) = d (ai, bi)
where
d (a, b) =
思路:
dp[i][j] 表示第i个位置上以数字j的结尾的距离
考虑两个状态之间的转换
对于节点k,若j,k 联通
若j == path[i] 那么dp[i][j] = dp[i - 1][k]
否则, dp[i][j] = dp[i - 1][k] + 1
#include <iostream>
#include <stdio.h>
#include <string.h>
#include <algorithm>
using namespace std;
#define maxn 110
#define inf 0x3f3f3f3f
int dp[220][220];
int path[220];
int map[maxn][maxn];
int val(int x){
if(x < 0) return -x;
return x;
}
int main()
{
int T,n,n1,n2;
while(~scanf("%d",&T)){
while(T--){
scanf("%d %d",&n1,&n2);
for(int i = 0; i <= n1; i ++)
for(int j = 0; j <= n1; j ++){
if(i == j) map[i][j] = 0;
else map[i][j] = -1;
}
int from,end;
while(n2--){
scanf("%d %d",&from,&end);
map[from][end] = 1;
map[end][from] = 1;
}
scanf("%d",&n);
for(int i = 1; i <= n; i ++)
scanf("%d",&path[i]);
memset(dp,inf,sizeof(dp));
for(int i = 1; i <= n1; i ++)
dp[1][i] = 1;
dp[1][path[1]] = 0;
for(int i = 2; i <= n; i ++){
for(int j = 1; j <= n1 ; j ++){
dp[i][j] = inf;
for(int k = 1; k <= n1; k ++){
if(map[j][k] != -1) {
if(j == path[i])
dp[i][j] = min(dp[i][j] , dp[i - 1][k]);
else
dp[i][j] = min(dp[i][j] , dp[i - 1][k] + 1);
}
}
}
}
int ans = inf;
for(int i = 1; i <= n1; i ++){
if(ans > dp[n][i]) ans = dp[n][i];
}
printf("%d\n",ans);
}
}
return 0;
}