您的位置:首页 > 其它

CodeVs 1036 商务旅行

2015-11-24 22:49 232 查看
http://codevs.cn/problem/1036/

LCA 模板

不知道为什么用模拟链表存边就 TLE 两组数据,vector 就过了 0.0

稀疏表

#include <stdio.h>
#include <vector>
#include <algorithm>
#include <cmath>

using std::vector;

const int MAXN = 30000 + 5;
const int MAXNN = MAXN << 1;

vector<vector<int> > G;

void initG(int n)
{
G.clear();
G.resize(n + 1);
}

int euler[MAXNN];
int depth[MAXNN];
int firstIn[MAXN];

void dfs(int u, int f, int& timestamp, int d)
{
euler[timestamp] = u;
depth[u] = d;
firstIn[u] = timestamp++;
for (int i = 0; i < (int) G[u].size(); i++) {
int v = G[u][i];
if (v == f)
continue;
dfs(v, u, timestamp, d + 1);
euler[timestamp++] = u;
}
}

#define POW(i) (1 << (i))
int stable[32][MAXNN];

void initRmq(int n)
{
for (int i = 0; i < n; i++)
stable[0][i] = euler[i];
for (int j = 1; POW(j) <= n; j++) {
for (int i = 0; i + POW(j) <= n; i++) {
int x = stable[j - 1][i];
int y = stable[j - 1][i + POW(j - 1)];
stable[j][i] = depth[x] > depth[y] ? y : x;
}
}
}

int lca(int u, int v)
{
int i = firstIn[u];
int j = firstIn[v];
if (i > j)
std::swap(i, j);
int k = log2(j - i + 1);
int x = stable[k][i];
int y = stable[k][j - POW(k) + 1];
int result = depth[x] > depth[y] ? y : x;
return result;
}

int main()
{
int n;
scanf("%d", &n);

initG(n);

int u, v;
for (int i = 1; i < n; i++) {
scanf("%d %d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}

int timestamp = 0;
dfs(1, -1, timestamp, 0);

initRmq(timestamp);

int sum = 0;

int m;
scanf("%d", &m);

u = 1;
for (int i = 1; i <= m; i++) {
scanf("%d", &v);
sum += depth[u] + depth[v] - 2 * depth[lca(u, v)];
u = v;
}

printf("%d\n", sum);
return 0;
}


Tarjan

#include <stdio.h>
#include <vector>
#include <string.h>

using namespace std;

const int MAXN = 30000 + 5;

vector<vector<int> > G;

void initEdges(int n)
{
G.clear();
G.resize(n + 1);
}

int id[MAXN];
int rnk[MAXN];

void initSets(int n)
{
for (int i = 1; i <= n; i++) {
id[i] = i;
rnk[i] = 1;
}
}

int root(int i)
{
if (i == id[i])
return i;
return id[i] = root(id[i]);
}

void unionSet(int x, int y)
{
if (rnk[x] > rnk[y])
id[y] = x;
else id[x] = y, rnk[y] += (rnk[x] == rnk[y]);
}

vector<vector<int> > query;

void inputQuery(int n)
{
query.clear();
query.resize(n + 1);
int m;
scanf("%d", &m);
for (int u = 1, v = 1; m--; ) {
scanf("%d", &v);
query[u].push_back(v);
query[v].push_back(u);
u = v;
}
}

int ancestor[MAXN];
bool vis[MAXN];
int depth[MAXN];

void initTarjan(int n)
{
initSets(n);
memset(vis, 0, sizeof(vis));
for (int i = 1; i <= n; i++)
ancestor[i] = i;
}

void tarjan(int u, int f, int& sum, int d)
{
depth[u] = d;
for (int i = 0; i < (int) G[u].size(); i++) {
int v = G[u][i];
if (v == f)
continue;
tarjan(v, u, sum, d + 1);
int rootU = root(u);
int rootV = root(v);
if (rootV != rootU)
unionSet(rootU, rootV);
ancestor[root(u)] = u;
}
vis[u] = true;
for (int i = 0; i < (int) query[u].size(); i++) {
int v = query[u][i];
if (!vis[v])
continue;
int dis = depth[u] + depth[v] - 2 * depth[ancestor[root(v)]];
sum += dis;
}
}

int main()
{
int n;
scanf("%d", &n);

initEdges(n);
int u, v;

for (int i = 0; i < n - 1; i++) {
scanf("%d %d", &u, &v);
G[u].push_back(v);
G[v].push_back(u);
}

inputQuery(n);

initTarjan(n);

int sum = 0;
tarjan(1, -1, sum, 0);

printf("%d\n", sum);
return 0;
}


  
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: