赛前测试一下模板用的~~~
Tarjan LCA离线算法
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <cassert>
#include <iostream>
#include <vector>
#include <utility>
#include <algorithm>
using namespace std;
const int MAXN = 10010;
const int MAXM = 1000010;
int n, m, c;
int head[MAXN], len; //存储图
int qhead[MAXN], qlen; //存储查询
int dis[MAXN], visit[MAXN];
int father[MAXN];
int ans[MAXM];
int id[MAXN];
struct Node
{
int v, w, next;
Node() {}
Node(int t_v, int t_w, int t_next) : v(t_v), w(t_w), next(t_next) {}
}edges[2*MAXN], query[2*MAXM];
void addEdge(int u, int v, int w)
{
edges[len].v = v, edges[len].w = w, edges[len].next = head[u];
head[u] = len++;
}
void addQuery(int u, int v, int id)
{
query[qlen].v = v, query[qlen].w = id, query[qlen].next = qhead[u];
qhead[u] = qlen++;
}
int find_set(int x)
{
return (father[x] == x ? x : father[x] = find_set(father[x]));
}
void Tarjan(int u, int root)
{
visit[u] = true; id[u] = root;
father[u] = u;
for(int i = qhead[u]; i != -1; i = query[i].next)
{
int v = query[i].v;
if(visit[v])
{
if(id[u] == id[v]) //属于同一连通分量
{
int rt = find_set(v);
ans[query[i].w] = dis[u] + dis[v] - 2 * dis[rt];
}
}
}
for(int i = head[u]; i != -1; i = edges[i].next)
{
int v = edges[i].v;
if(!visit[v])
{
dis[v] = dis[u] + edges[i].w;
Tarjan(v, root);
father[v] = u;
}
}
return ;
}
void Init()
{
for(int i = 1; i <= n; ++i)
{
father[i] = i;
}
len = qlen = 0;
memset(id, -1, sizeof(id));
memset(head, -1, sizeof(head));
memset(qhead, -1, sizeof(qhead));
memset(visit, false, sizeof(visit));
memset(ans, -1, sizeof(ans));
}
int main()
{
//freopen("aa.in", "r", stdin);
//freopen("bb.out", "w", stdout);
int u, v, w;
while(scanf("%d %d %d", &n, &m, &c) != EOF)
{
Init();
for(int i = 1; i <= m; ++i)
{
scanf("%d %d %d", &u, &v, &w);
addEdge(u, v, w);
addEdge(v, u, w);
}
for(int i = 1; i <= c; ++i)
{
scanf("%d %d", &u, &v);
addQuery(u, v, i);
addQuery(v, u, i);
}
for(int i = 1; i <= n; ++i)
{
if(!visit[i])
{
Tarjan(i, i);
}
}
for(int i = 1; i <= c; ++i)
{
if(ans[i] < 0)
printf("Not connected\n");
else
printf("%d\n", ans[i]);
}
}
return 0;
}
RMQ&LCA 在线算法
#include <cmath>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <iostream>
#include <algorithm>
using namespace std;
const int M = 25;
const int MAXN = 10010;
const int MAXM = 1000010;
struct Edge
{
int u, v, w, next;
Edge() {}
Edge(int t_u, int t_v, int t_w, int t_next) : u(t_u), v(t_v), w(t_w), next(t_next) {}
}edges[2*MAXN];
int head[MAXN];
int power[M];
int ver[2*MAXN], R[2*MAXN], first[MAXN], dis[MAXN];
int dp[2*MAXN][25];
bool visit[MAXN];
int parent[MAXN];
int len, tot;
inline void addEdge(int u , int v, int w)
{
edges[len].u = u, edges[len].v = v, edges[len].w = w, edges[len].next = head[u], head[u] = len++;
edges[len].v = v, edges[len].v = u, edges[len].w = w, edges[len].next = head[v], head[v] = len++;
}
void dfs(int u , int dep)
{
visit[u] = true; first[u] = ++tot; ver[tot] = u; R[tot] = dep;
for(int i = head[u]; i != -1; i = edges[i].next)
{
if(!visit[edges[i].v])
{
int v = edges[i].v , w = edges[i].w;
dis[v] = dis[u] + w;
dfs(v, dep + 1);
ver[++tot] = u; R[tot] = dep;
}
}
}
void RMQ_Init(int len)
{
int K = (int)(log((double)(len))/log(2.0));
for(int i = 1; i <= len; i++) dp[i][0] = i;
for(int j = 1; j <= K; ++j)
{
for(int i = 1; i + power[j] - 1 <= len; ++i)
{
int a = dp[i][j-1] , b = dp[i + power[j-1]][j-1];
if(R[a] < R[b])
dp[i][j] = a;
else
dp[i][j] = b;
}
}
return ;
}
int RMQ_Query(int x, int y)
{
int K = (int)(log((double)(y-x+1)) / log(2.0));
int a = dp[x][K] , b = dp[y - power[K] + 1][K];
if(R[a] < R[b])
return a;
else
return b;
}
int LCA(int u ,int v)
{
int x = first[u] , y = first[v];
if(x > y) swap(x, y);
int index = RMQ_Query(x, y);
return ver[index];
}
void Init()
{
len = tot = 0;
memset(head, -1, sizeof(head));
memset(visit, false, sizeof(visit));
memset(dis, 0, sizeof(dis));
memset(parent, -1, sizeof(parent));
}
int find_set(int x)
{
return (parent[x] < 0 ? x : parent[x] = find_set(parent[x]));
}
void union_set(int x, int y)
{
int r1 = find_set(x), r2 = find_set(y);
if(r1 != r2)
{
if(parent[r2] < parent[r1])
{
parent[r2] += parent[r1];
parent[r1] = r2;
}
else
{
parent[r1] += parent[r2];
parent[r2] = r1;
}
}
}
int main()
{
//freopen("aa.in", "r", stdin);
//freopen("bb.out", "w", stdout);
for(int i = 0; i < M; ++i)
power[i] = (1<<i);
int n, m, c, u, v, w;
while(scanf("%d %d %d", &n, &m, &c) != EOF)
{
Init();
for(int i = 1; i <= m; ++i)
{
scanf("%d %d %d", &u, &v, &w);
union_set(u, v);
addEdge(u, v, w);
}
for(int i = 1; i <= n; ++i)
{
if(!visit[i])
{
dfs(i, 1);
}
}
RMQ_Init(tot);
for(int i = 1; i <= c; ++i)
{
scanf("%d %d", &u, &v);
if(find_set(u) != find_set(v))
{
printf("Not connected\n");
}
else
{
int lca = LCA(u, v);
printf("%d\n", dis[u] + dis[v] - 2 * dis[lca]);
}
}
}
return 0;
}