luogu 1967 货车运输(2)

突然发现dfs改成我自己的方式也可以的哦!!!!!

include

include

include

include

include

using namespace std;
const int maxn = 100005;
const int maxm = 100005;
int n,m,head[maxn],father[maxn],top,depth[maxn],par[maxn][22],pre[maxn][22];
int ans = 1e9;
struct edge_pro {
int st,en,value;
}ea[maxm<<1];
//题目要求的树
struct edge {
int next,to,value;
}e[maxm<<1];
//最大生成树里的树
bool cmp (edge_pro a,edge_pro b) {
return a.value >b.value;
}

int find(int x) {
if(father[x] == x) return x;
return father[x] = find(father[x]);
}

void unionn (int r1,int r2) {
if(find(r1) != find(r2))
father[find(r1)] = find(r2);
}

void add_edge(int u,int v,int w) {
e[++top].next = head[u];
e[top].value = w;
e[top].to = v;
head[u] = top;
}

void dfs(int u,int fa) {
depth[u] = depth[fa] + 1;
for(int i = 1;(1 << i)<= depth[u] ;++i) {
par[u][i] = par[par[u][i - 1]][i - 1];
pre[u][i] = min(pre[u][i - 1] , pre[par[u][i - 1]][i - 1]);
}
for(int i = head[u] ; i ;i = e[i].next)
if(e[i].to != fa){
pre[e[i].to][0] = e[i].value;
par[e[i].to][0] = u;
dfs(e[i].to , u);
}
}

int lca(int x,int y) {
if(find(x) != find(y)) return -1;
ans = 1e9;
if(depth[x] < depth[y]) swap(x , y);
for(int i = log(n);i >= 0 ;–i)
if(depth[par[x][i]] >= depth[y]) {
ans = min(pre[x][i] , ans); //重点!重点!(本人在这里卡了一万次)
x = par[x][i]; //这两行顺序不能乱的哦 需要先更新ans 再去重新赋值x 下面也是
}
if(x == y) return ans;
for(int j = log(n);j >= 0 ;–j)
if(par[x][j] != par[y][j]){
ans = min(ans , min(pre[x][j] , pre[y][j]));
x = par[x][j] , y = par[y][j];
}
ans = min(ans , min(pre[x][0] , pre[y][0]));
return ans;
}

int main() {
scanf(“%d%d”,&n,&m);
for(int i = 1;i <= m ;++i) {
int x,y,z; scanf(“%d%d%d”,&x,&y,&z);
ea[i].st = x; ea[i].en = y;
ea[i].value = z;
}
for(int i = 1;i <= n ;++i) father[i] = i;
sort(ea + 1,ea + m + 1,cmp);
int k = 0;
for(int i = 1;i <= m ;++i) {
if(find(ea[i].st) != find(ea[i].en)) {
unionn(ea[i].st , ea[i].en) ; k++;
add_edge(ea[i].st , ea[i].en , ea[i].value);
add_edge(ea[i].en , ea[i].st , ea[i].value);
}
if(k == n - 1) break;
}
//以上是生成树的内容啦…
for(int i = 1;i <= n ;++i)
if(!depth[i]) { //这个地方我个人理解为可能有多个并查集的意思 maybe生成树很多吧
depth[i] = 1;
dfs(i , 0);
}
int q; scanf(“%d”,&q);
while(q–) {
int x,y; scanf(“%d%d”,&x,&y);
printf(“%d\n”,lca(x , y));
}
return 0;
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值