Description
N个城镇,选M个,让这些M个城镇连起来,两个城镇有一个花费,问最小花费多少
Hint
You may suppose that the initial transportation network makes up a tree.
多方暗示,路径只有N-1条,这正是树的性质
Data Structure
怎么存这棵树?
我选择邻接表
g[x][y] 表示 x节点后面的第y个节点的节点号 g[x][0]记录x节点总共有多少个节点
然后c数组来记录权,不想写结构体,因为写结构体用g[x][0]这个技巧就很奇怪
Algorithm
DFS因为是树,所以任意两个点有且只有一条路,遍历一遍树就是了
如果这个节点之下有需要连通的节点,ans就加上这条边
Code
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;
const int maxn = 1000 + 9;
int n, m;
bool a[maxn]; // 记录需要包括的m个点
int g[maxn][maxn]; //邻接表 记录点
int c[maxn][maxn]; //邻接表 记录cost
bool d[maxn]; //记录每个点是否访问过
int ans = 0;
bool dfs(const int &x)
{
int flag = false;
d[x] = true;
for (int i = 1; i <= g[x][0]; i++)
if (!d[g[x][i]] && dfs(g[x][i]))
{
flag = true;
ans += c[x][i];
}
if (a[x] || flag) return true;
}
void solve()
{
memset(a, 0, sizeof(a));
memset(g, 0, sizeof(g));
memset(c, 0, sizeof(c));
memset(d, 0, sizeof(d));
ans = 0;
int s; //开始搜的点
scanf("%d", &s);
a[s] = true;
for (int i = 1; i < m; i++)
{
int x;
scanf("%d", &x);
a[x] = true;
}
for (int i = 0; i < n - 1; i++)
{
int aa, b, cc;
scanf("%d%d%d", &aa, &b, &cc);
g[aa][++g[aa][0]] = b;
c[aa][g[aa][0]] = cc;
g[b][++g[b][0]] = aa;
c[b][g[b][0]] = cc;
}
dfs(s);
cout << ans << endl;
}
int main()
{
while (scanf("%d%d", &n, &m) != EOF)
solve();
}