bzoj 2282: [Sdoi2011]消防

来源:互联网 发布:wingware python ide 编辑:程序博客网 时间:2024/06/02 12:04

题意:在一棵树中选一条长度不超过s的路径,使其他所有城市到这条路径的最远距离最小。
题解:树的直径+单调队列
先求出树的直径,再用单调队列搞一搞就好了。
代码:

#include<cstdio>#include<cstring>#include<queue>#include<algorithm>#include<vector>using namespace std;int n,s,num=0,fst[300010],dis[300010],pre[300010],maxd[300010],dd[300010],ans=2147483647;struct edge{    int x,y,c,n;}e[600010];bool v[300010];vector<int>d,en;void ins(int x,int y,int c){    e[++num]={x,y,c,fst[x]};    fst[x]=num;}int bfs(int s){    static queue<int>q;    q.push(s);    memset(dis,63,sizeof(dis));    dis[s]=0;    v[s]=1;    int t=s;    memset(pre,0,sizeof(pre));    while(!q.empty())    {        int x=q.front();        v[x]=0;        if(dis[x]>dis[t])        t=x;        for(int i=fst[x];i;i=e[i].n)        {            int y=e[i].y;            if(!v[y]&&dis[y]>dis[x]+e[i].c)            {                dis[y]=dis[x]+e[i].c;                pre[y]=i;                v[y]=1;                q.push(y);            }        }        q.pop();    }    return t;}int main(){    scanf("%d%d",&n,&s);    for(int i=1;i<n;i++)    {        int x,y,c;        scanf("%d%d%d",&x,&y,&c);        ins(x,y,c);        ins(y,x,c);    }    int st=bfs(1);    memset(v,0,sizeof(v));    int ed=bfs(st);    for(int i=ed;i;i=e[pre[i]].x)    {        v[i]=1;        d.push_back(i);        en.push_back(pre[i]);    }    for(int i=0;i<d.size();i++)    {        maxd[i]=dis[bfs(d[i])];        v[d[i]]=1;    }    dd[0]=0;    for(int i=0;i<d.size()-1;i++)    dd[i+1]=dd[i]+e[en[i]].c;/*    for(int i=0;i<d.size();i++)    printf("d:%d en:%d maxd:%d dd:%d\n",d[i],en[i],maxd[i],dd[i]);*/    int l=0;    deque<int>q;    for(int r=0;r<d.size();r++)    {        while(!q.empty()&&maxd[r]>q.back())        q.pop_back();        q.push_back(maxd[r]);        while(dd[r]-dd[l]>s)        {            if(maxd[l]==q.front())            q.pop_front();            l++;        }        ans=min(ans,max(max(max(dd[l],maxd[l]),max(dd[d.size()-1]-dd[r],maxd[r])),q.front()));//      printf("%d %d %d\n",l,r,ans);    }    printf("%d",ans);}
原创粉丝点击