题意:给定一个n(2<=n<=30000)个点m(n<=m<=50000)条边的无向图,选出权值和最大的生成树,给q(1<=q<=30000)个询问u->v路径上顺序
得到的ci cj(i <= j)的cj - ci最大值是多少。
题解:kruskal搞掉最大生成树,并查集维护up[] dw[] ma[] mi[] 分别表示从当前点走到lca的最优值,从lca走到当前点的最优值,从当点走到lca的最大值,
从lca走到当前点的最小值即可。
PS:比赛的时候把并查集搞错了唉,但是还是搞到了这个fb。
Sure原创,转载请注明出处。
#include <iostream>
#include <cstdio>
#include <memory.h>
#include <algorithm>
#define MAX(a , b) ((a) > (b) ? (a) : (b))
#define MIN(a , b) ((a) < (b) ? (a) : (b))
using namespace std;
const int maxm = 50002;
const int maxn = 30002;
struct record
{
int u,v,w;
bool operator < (const record &other) const
{
return w > other.w;
}
}EE[maxm];
struct node
{
int v;
int next;
}edge[maxn << 1];
struct QQ
{
int u,v,id;
int next;
}query[maxn << 1];
struct LL
{
int have,next;
}lca[maxn];
int head[maxn],qhead[maxn],lcahead[maxn];
int angry[maxn],father[maxn],ans[maxn];
int ma[maxn],mi[maxn],up[maxn],dw[maxn];
bool vis[maxn];
int m,n,idx,tot,top,sum;
void swap(int &a,int &b)
{
int tmp = a;
a = b;
b = tmp;
return;
}
void init()
{
memset(head,-1,sizeof(head));
memset(qhead,-1,sizeof(qhead));
memset(lcahead,-1,sizeof(lcahead));
memset(vis,false,sizeof(vis));
for(int i=1;i<=n;i++)
{
father[i] = i;
}
idx = tot = top = sum = 0;
return;
}
int gg(int u)
{
return (u == father[u]) ? father[u] : (father[u] = gg(father[u]));
}
void read()
{
for(int i=1;i<=n;i++)
{
scanf("%d",&angry[i]);
ma[i] = mi[i] = angry[i];
up[i] = dw[i] = 0;
}
scanf("%d",&m);
for(int i=0;i<m;i++)
{
scanf("%d %d %d",&EE[i].u,&EE[i].v,&EE[i].w);
}
sort(EE , EE + m);
return;
}
void addedge(int u,int v)
{
edge[idx].v = v;
edge[idx].next = head[u];
head[u] = idx++;
edge[idx].v = u;
edge[idx].next = head[v];
head[v] = idx++;
return;
}
void addquery(int u,int v,int num)
{
query[tot].u = u;
query[tot].v = v;
query[tot].id = num;
query[tot].next = qhead[u];
qhead[u] = tot++;
query[tot].u = v;
query[tot].v = u;
query[tot].id = num;
query[tot].next = qhead[v];
qhead[v] = tot++;
return;
}
void kruskal()
{
for(int i=0;i<m;i++)
{
int x = gg(EE[i].u);
int y = gg(EE[i].v);
if(x != y)
{
sum += EE[i].w;
father[y] = x;
addedge(EE[i].u , EE[i].v);
}
}
printf("%d\n",sum);
return;
}
int find(int u)
{
if(u == father[u]) return father[u];
int tmp = father[u];
father[u] = find(father[u]);
up[u] = MAX(ma[tmp] - mi[u] , MAX(up[u] , up[tmp]));
dw[u] = MAX(ma[u] - mi[tmp] , MAX(dw[u] , dw[tmp]));
ma[u] = MAX(ma[u] , ma[tmp]);
mi[u] = MIN(mi[u] , mi[tmp]);
return father[u];
}
void dfs(int st)
{
vis[st] = true;
for(int i=qhead[st];i != -1;i=query[i].next)
{
if(vis[query[i].v])
{
int x = find(query[i].v);
lca[top].have = i;
lca[top].next = lcahead[x];
lcahead[x] = top++;
}
}
for(int i=head[st];i != -1;i=edge[i].next)
{
if(vis[edge[i].v] == false)
{
dfs(edge[i].v);
father[edge[i].v] = st;
}
}
for(int i=lcahead[st];i != -1;i=lca[i].next)
{
int id = lca[i].have;
int u = query[id].u;
int v = query[id].v;
find(u);
if(id & 1) swap(u , v);
ans[query[id].id] = MAX(ma[v] - mi[u] , MAX(up[u] , dw[v]));
}
return;
}
void solve()
{
scanf("%d",&m);
int u,v;
for(int i=0;i<m;i++)
{
scanf("%d %d",&u,&v);
addquery(u,v,i);
}
for(int i=1;i<=n;i++)
{
father[i] = i;
}
dfs(1);
for(int i=0;i<m;i++)
{
printf("%d\n",ans[i]);
}
return;
}
int main()
{
while(~scanf("%d",&n))
{
init();
read();
kruskal();
solve();
}
return 0;
}