【NOIP2015】【bzoj4326】运输计划 LCA+差分+二分答案

来源:互联网 发布:中小学辅导网络 编辑:程序博客网 时间:2024/05/16 08:01

这里写图片描述
这里写图片描述
NOIP2015最后一题,实际上不难,艹起来比D1T3(斗地主)舒服多了


听说要卡常,求LCA就从倍增换成了tarjan,但不知道noip的老爷机过得了不,反正bzoj我感觉7860ms还不是很慢


然后大概思路很简单,先二分答案,检验的时候差分,在对所有比枚举值大的路径lca-=2,s++,v++然后dfs找都经过的边就可以了
程序见下:

#include<iostream>#include<cstdio>#include<cstring>#include<string>#include<set>#include<map>#include<queue>#include<algorithm>#include<vector>#include<cstdlib>#include<cmath>#include<ctime>#include<stack>#define INF 2100000000#define ll long long#define clr(x)  memset(x,0,sizeof(x))#define maxclr(x)  memset(x,127,sizeof(x))#pragma comment(linker,"/STACK:102400000,1024000")using namespace std;inline int read(){    char c='q';    int ret=0;    while(!(c>='0'&&c<='9'))        c=getchar();    while(c>='0'&&c<='9')    {        ret=(c-'0')+(ret<<1)+(ret<<3);        c=getchar();    }    return ret;}#define M 300005int first[M],lext[M<<1],to[M<<1],d[M<<1],t;int fa[M],ufa[M],lca[M],lcad[M],vis[M],dis[M];int first2[M],next2[M<<1],to2[M<<1],num[M<<1],t2;int S[M],V[M],cf[M];int n,m,mx,sum;void addedge(int s,int v,int val){    lext[++t]=first[s];    first[s]=t;    to[t]=v;    d[t]=val;}void addedge2(int s,int v,int fig){    next2[++t2]=first2[s];    first2[s]=t2;    to2[t2]=v;    num[t2]=fig;}int get_fa(int x){    return x==ufa[x]?x:ufa[x]=get_fa(ufa[x]);}inline void tarjan(int x,int w){    dis[x]=w;    vis[x]=1;    ufa[x]=x;    for(int i=first[x];i;i=lext[i])    {        int v=to[i];        if(v==fa[x])continue;        fa[v]=x;        tarjan(v,w+d[i]);        ufa[v]=x;    }    for(int i=first2[x];i;i=next2[i])    {        int v=to2[i],p=num[i];        if(!vis[v])continue;        lca[p]=get_fa(v);        lcad[p]=dis[x]+dis[v]-dis[lca[p]]*2;        mx=max(mx,lcad[p]);    }}inline void dfs(int x){    for(int i=first[x];i;i=lext[i])    {        int v=to[i];        if(v==fa[x])continue;        dfs(v);        if(cf[v]==sum)            mx=max(mx,d[i]);        cf[x]+=cf[v];    }}bool check(int x){    sum=0;    int maxx=0;    clr(cf);    for(int i=1;i<=m;i++)        if(lcad[i]>x)        {            sum++;            cf[S[i]]++;            cf[V[i]]++;            cf[lca[i]]-=2;            maxx=max(maxx,lcad[i]);        }    if(sum==0)return 1;    mx=0;    dfs(1);    return maxx-mx<=x;}int main(){    freopen("transport.in","r",stdin);    freopen("transport.out","w",stdout);    n=read();m=read();    for(int i=1;i<n;i++)    {        int a=read(),b=read(),c=read();        addedge(a,b,c);        addedge(b,a,c);    }    for(int i=1;i<=m;i++)    {        int a=read(),b=read();        addedge2(a,b,i);        addedge2(b,a,i);        S[i]=a;        V[i]=b;    }    tarjan(1,0);    int l=0,r=mx+1,mid;    while(r>l)    {        mid=(l+r)>>1;        if(check(mid))r=mid;        else l=mid+1;    }    printf("%d",l);    return 0;}

大概就是这个样子,如果有什么问题,或错误,请在评论区提出,谢谢。

0 0
原创粉丝点击