2013年noip第三题货车运输truck(树链剖分LCA+最大生成树)

写这个题的时候,其实已经手撸出LCA——树链剖分算法,

下面给出一段我的LCAn模板,说真的真的很好写不能更好写了,大家可以看看别的算法再来看我的实现,个人觉得写的还不错(一定要先有了解不然可能看不懂)

int dis[maxn], htop[maxn], sz[maxn], dep[maxn], hson[maxn], dist[maxn], fa[maxn];
//sz[],当前节点孩子数目,htop[]当前节点所处重链,dep[]当前节点的深度,hson[]是这个节点的孩子中sz[]数组最大的节点,dist[]是从此节点到根的距离
//fa[]他爹
void dfs1(int u){
    sz[u] = 1;
    for(int i = begin[u]; i; i = next[i])
        if(to[i] != fa[u]){
            int v = to[i];
            fa[v] = u;
            dep[v] = dep[u] + 1;
            dis[v] = dis[u] + w[i];
            dfs1(v);
            if(sz[v] > sz[hson[u]])hson[u] = v;
            sz[u] += sz[v];
        }
}

void dfs2(int u, int v){
    htop[u] = v;
        for(int i = begin[u]; i; i = next[i]){
            int j = to[i];
            if(htop[j])continue;
            if(hson[u] == j)dfs2(j, v);
            else dfs2(j, j);
        }
}

int lca(int a,int b){
    while(htop[a] != htop[b]){
        if(dep[htop[a]] < dep[htop[b]]){int t;t=a;a=b;b=t;}
        a=fa[htop[a]];
    }
    return dep[a] < dep[b]?a : b;
}
这是模板,虽然下面的实现用不到这么多,但我还是写上吧;大家可以做参考,再写一个博客太累了。。。。。

接着到本题,其实很好理解,就是先用最大生成树,什么?怎么求->直接sort贪心拿最大值,所求的路径必定是最大生成树上的一条,否则不符合最大生成树定义

写这个博客主要是犯了很都比的错误,邻接表写错一个字母啊,sort排边写成n点的个数吐了;

还有就是开始写的时候写到查找的时候,发现顺序被打乱离线不好求,于是想参考网上的代码;

但是居然没有一个人写tarjan

#include<cstdio>
#include<cstring> 
#include<algorithm>
#define N 40010
#define M 100010 
using namespace std;
int n, m;
int start[N], nxt[N], to[N], ee, f[N];
int dep[N], dist[N],fa[N],w[N];
struct truck{
	int x,y,w;
}e[M];
bool cmp(truck a, truck b){return a.w>b.w;}
void read(int &x){
	char c=getchar();
	x=0;
	while(c<'0' || c>'9')c=getchar();
	while(c>='0' && c<= '9'){
		x=x*10+c-'0';
		c=getchar();
	}
}
bool vis[N];
void dfs(int u)
{
    vis[u]=true;
    for(int i = start[u]; i; i=nxt[i])
        if(!vis[to[i]])
        {
            fa[to[i]]=u;
            dist[to[i]]=w[i];
            dep[to[i]]=dep[u] + 1;
            dfs(to[i]);
        }
}
int check(int t1,int t2){
	int mn1 = 0x7f7f7f7f, mn2 = 0x7f7f7f7f;
    if(dep[t1] < dep[t2]) swap(t1, t2);
    while(dep[t1] > dep[t2])
    {
        mn1=min(mn1, dist[t1]);
        t1=fa[t1];
    }
    while(t1!=t2)
    {
        mn1=min(mn1, dist[t1]);
        t1=fa[t1];
        mn2=min(mn2, dist[t2]);
        t2=fa[t2];
    }
    return min(mn1, mn2);
}
void add(int x, int y,int z){
	to[++ee]=y;
	nxt[ee]=start[x];
	start[x]=ee;
	w[ee]=z;
}
int find(int x){
    if(f[x]!=x)return f[x]=find(f[x]);
    return f[x];
}
int main(){
	read(n);read(m);
	for(int i=1; i<=m; ++i)read(e[i].x),read(e[i].y),read(e[i].w);
	for(int i=1; i<=n; ++i)f[i]=i;
	sort(e+1,e+m+1,cmp);
	int tot=0;
	for(int i=1; i<=m; ++i){
		int a=find(e[i].x), b=find(e[i].y);
		if(a!=b){
			f[a]=b;
			add(e[i].x,e[i].y,e[i].w);
			add(e[i].y,e[i].x,e[i].w);
			tot ++;
			if(tot==n-1)break;
		}
	}
	for(int i=1; i<=n; ++i)if(!vis[i])dfs(i);
	int q, x, y;
	read(q);
	for(int i=1; i<=q; ++i){
		read(x);read(y);
		if(find(x)!=find(y)){puts("-1");continue;}
		printf("%d\n",check(x,y));
	} 
	return 0;
}
/*
4 3
1 2 4
2 3 3
3 1 1
3
1 3
1 4
1 3
*/

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值