zoukankan      html  css  js  c++  java
  • 解题报告:luogu P1099

    题目链接:P1099 树网的核
    树形(dp)
    不会,连暴力(O(n^3))都不会。
    只有(64;pts)(似乎能(80)?)。
    暴力:

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    using namespace std;
    const int MAXN=305;
    int d[MAXN],dis[MAXN],ms,md=0,c=1;
    int disl[MAXN],disr[MAXN],id[MAXN],rt[MAXN];
    int ans=2147483647;
    struct node
    {
    	int l,to,nxt;
    }e[MAXN<<1];
    int head[MAXN],cnt=0;
    void add(int u,int v,int w)
    {
    	e[++cnt].to=v;
    	e[cnt].l=w;
    	e[cnt].nxt=head[u];
    	head[u]=cnt;
    }
    int n,m,l,r,z;
    void dfs1(int cur,int fa,int step)
    {
    	dis[cur]=step;
    	for(int i=head[cur];i;i=e[i].nxt)
    	{
    		int j=e[i].to;
    		if(j!=fa) dfs1(j,cur,step+e[i].l);
    	}
    	if(dis[cur]>md) md=dis[cur],ms=cur;
    	return;
    }
    void dfs2(int cur)
    {
    	for(int i=head[cur];i;i=e[i].nxt)
    	{
    		int j=e[i].to;
    		if(dis[j]<dis[cur]) d[++c]=j,dfs2(j);
    	}
    	return;
    }
    void dfs3(int cur,int fa,int step)
    {
    	disl[cur]=step;
    	for(int i=head[cur];i;i=e[i].nxt)
    	{
    		int j=e[i].to;
    		if(j!=fa) dfs3(j,cur,step+e[i].l);
    	}
    	return;
    }
    void dfs4(int cur,int fa,int step)
    {
    	disr[cur]=step;
    	for(int i=head[cur];i;i=e[i].nxt)
    	{
    		int j=e[i].to;
    		if(j!=fa) dfs4(j,cur,step+e[i].l);
    	}
    	return;
    }
    int ee(int l,int r,int lfa,int rfa,int sum)
    {
    	int maxn=max(min(disl[l],disl[r]),min(disr[l],disr[r]));
    	for(int i=head[l];i;i=e[i].nxt)
    	{
    		int j=e[i].to;
    		if(sum>=e[i].l&&j!=lfa) maxn=min(maxn,ee(j,r,l,rfa,sum-e[i].l));
    	}
    	for(int i=head[r];i;i=e[i].nxt)
    	{
    		int j=e[i].to;
    		if(sum>=e[i].l&&j!=rfa) maxn=min(maxn,ee(l,j,lfa,r,sum-e[i].l));
    	}
    	return maxn;
    }
    int main()
    {
    	scanf("%d%d",&n,&m);
    	for(int i=1;i<n;i++)
    	{
    		scanf("%d%d%d",&l,&r,&z);
    		add(l,r,z);
    		add(r,l,z);
    	}
    	dfs1(1,0,0); 
    	memset(dis,0,sizeof(dis));
    	md=0;
    	dfs1(ms,0,0);
    	d[1]=ms;
    	dfs2(ms);
    	disl[d[1]]=0;
    	dfs3(d[1],0,0);
    	disr[d[c]]=0;
    	dfs4(d[c],0,0);
    	for(int i=1;i<=n;i++) ans=min(ans,ee(i,i,0,0,m));
    	printf("%d
    ",ans);
    	return 0;
    } 
    

    正解:

    #include<cstdio>
    #include<algorithm>
    #define M 500005
    using namespace std;
    int n,m,x,y,z,k,id,top,ans=2e9;
    int dis[M],fa[M],head[M];
    bool mark[M];
    struct edge
    {
        int to,w,nxt;
    }E[M<<1];
    void add(int u,int v,int w)
    {
        E[++id]=((edge){v,w,head[u]});
        head[u]=id;
    }
    void dfs(int f,int x){
        fa[x]=f;
        if(dis[x]>dis[k])k=x;
        for(int i=head[x];i;i=E[i].nxt)
    	{
            int y=E[i].to;
            if(y==f||mark[y]) continue;
            dis[y]=dis[x]+E[i].w;
            dfs(x,y);
        }
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for(int i=1;i<n;i++)
    	{
            scanf("%d%d%d",&x,&y,&z);
            add(x,y,z),add(y,x,z);
        }
        dis[1]=1,dfs(0,1);
        dis[k]=0,dfs(0,k);
        top=k;
        for(int i=top,j=top,l=1,r=0;i;i=fa[i])
    	{
            while(dis[j]-dis[i]>m) j=fa[j];
            x=max(dis[top]-dis[j],dis[i]);
            ans=min(ans,x);
        }
        for(int i=top;i;i=fa[i]) mark[i]=1;
        for(int i=top;i;i=fa[i])
    	{
            k=i,dis[k]=0;
            dfs(fa[i],i);
        }
        for(int i=1;i<=n;i++) ans=max(ans,dis[i]);
        printf("%d
    ",ans);
        return 0;
    }
    

    大概就是直径上尺取,然后有两种情况,具体看题解去吧。

  • 相关阅读:
    单例设计模式
    网络编程--Socket与ServerSocket
    JDBC连接Oracle数据库
    ObjectInputStream与ObjectOutputStream
    MyBatis的SQL语句映射文件详解(二)----增删改查
    MyBatis的SQL语句映射文件详解
    MyBatis+Spring实现基本CRUD操作
    通俗解释IOC原理
    Git菜鸟
    hibernate连接oracle数据库
  • 原文地址:https://www.cnblogs.com/tlx-blog/p/12401623.html
Copyright © 2011-2022 走看看