BZOJ3124: [Sdoi2013]直径

版权声明:原创文章,转载要注明作者哦 https://blog.csdn.net/DYT_B/article/details/81267749

题目描述:戳这里
题解:
这题是一道比较经典的和直径有关的题目。我们首先肯定要刷出直径。
有一个关于直径的结论,如果有多条直径,那么它们相交的部分肯定是连续的一段(yy一下应该能想出来)。
那么在我们刷出来的直径中,为什么会出现一条边没有被所有直径经过呢,那么肯定是从直径上的某一个在它之前的点有至少两条最长路径,那么这个点在某一条中,那么肯定就不满足题目条件了。
我们思考一下,是不是只要对于直径上的每一个点刷一下最长路和次长路就可以了。
但是这样的复杂度好像不是那么科学。
其实我们完全可以不用这么做,一个点的最长路肯定在直径上,我们只要刷出次长路,也就是非当前直径路径的最长路就可以了。一位一条非直径路径肯定是由直径上的某一个点延伸出去的,那么这样就保证了每个点只被刷到一次。
然后我们只要正着刷出一个tail,反着刷出一个head,那么从head到tail这连续的一段就是我们要求的答案了。

代码如下:(代码有点糟乱)

#include<cstdio>
#include<string>
#include<cstring>
#define ll long long
using namespace std;
const int maxn=200005;
int T,n,tot,lnk[maxn],w[2*maxn],nxt[2*maxn],son[2*maxn],father[maxn],g[maxn];
ll dis[2][maxn],maxx[maxn];
bool vis[maxn];
int m,que[maxn];
void add(int x,int y,int z){
    son[++tot]=y,nxt[tot]=lnk[x],w[tot]=z,lnk[x]=tot;
}
void dfs(int x,int fa,int num){
    father[x]=fa;
    for (int j=lnk[x];j;j=nxt[j])
    if (son[j]!=fa) {
        dis[num][son[j]]=dis[num][x]+w[j];
        dfs(son[j],x,num);
    }
}
void make_(){
    dfs(1,0,0); int id=1;
    for (int i=2;i<=n;i++)
    if (dis[0][i]>dis[0][id]) id=i;
    memset(father,0,sizeof(father));
    dfs(id,0,1); int id1=1;
    for (int i=2;i<=n;i++)
    if (i!=id&&dis[1][i]>dis[1][id1]) id1=i;
    printf("%lld\n",dis[1][id1]);
    while (id1!=id) {
        que[++m]=id1;
        id1=father[id1];
    }
    que[++m]=id;    
}
void dfs1(int x,int num){
    for (int j=lnk[x];j;j=nxt[j])
    if (!vis[son[j]]) {
        vis[son[j]]=1; g[son[j]]=g[x]+w[j];
        dfs1(son[j],num);
    }
    if (g[x]>maxx[num]) maxx[num]=g[x];
}
int main(){
    scanf("%d",&n);
    for (int i=1;i<n;i++) {
        int x,y,z; scanf("%d %d %d",&x,&y,&z);
        add(x,y,z); add(y,x,z);
    }
    make_();
    int head=1,tail=4;
    for (int i=1;i<=m;i++) vis[que[i]]=1;
    for (int i=1;i<=m;i++) {dfs1(que[i],que[i]); if (maxx[que[i]]>0&&maxx[que[i]]==dis[1][que[i]]-dis[1][que[m]]) {tail=i; break;}}
    for (int i=m;i>=1;i--) if (maxx[que[i]]>0&&maxx[que[i]]==dis[1][que[1]]-dis[1][que[i]]) {head=i; break;}
    printf("%d\n",max(1,tail-head));
    return 0;
}

猜你喜欢

转载自blog.csdn.net/DYT_B/article/details/81267749