HDU 3274 City Planning

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();
}

你可能感兴趣的:(HDU 3274 City Planning)