hdu4916 Count on the path

来源:互联网 发布:性知识软件哪些好 编辑:程序博客网 时间:2024/06/08 12:33

 2014 Multi-University Training Contest 5 F题。

题目大意:给定一颗n个节点的树,q个查询,每次查询输入两个端点(u,v),代表树上一条从u->v的路径,求删掉这条路径上的点后,剩下的点中编号最小的点。

题目分析:可以这样想象:(1)我们以1这个节点为根,删掉根节点后形成若干个联通分量,很显然若路径中的两个端点在删掉根节点后还在同一个联通分量中,那么所求结果必然为1。这个可在预处理后O(1)实现(2)若两个端点不在同一个联通分量中,那么必然经过根节点,此时若纯暴力则时间复杂度可达O(n*q)之大,题目数据量非常大,必然死掉。 官方的题解给了做题的方向,可以用树形DP的思想,预处理求出每个节点的f[]值,f[u]代表从u到他所属的根节点(删除1之后的)除去路径上的点后编号最小的点值。

如下图所示,所求的值f[2]=4,f[3]=7,f[4]=5,f[5]=6,f[7]=8,f[8]=7,f[9]=8;

2所对应的根节点为2,f[2]=min(与2同属于一个联通分量且不在2到根节点的链上的,2以下的节点中编号最小的);

求出所有的f[]值后,还需知道各个联通分量中编号最小的点,因为当根节点1的儿子节点有多个,即有多个联通分量时 ,两个端点分属两个联通分量,最小值可能出现在别的联通分量中,但f[]值没有考虑到。 则我们需要保存编号最小的三个联通分量。

比较绕口,过后补上图解。


#include<iostream>#include<cstdlib>#include<cstdio>#include<cstring>#include<vector>#include<stack>#include<algorithm>#include<queue>struct node{    int u,parent;    node(){}    node(int x,int y)    {        u=x,parent=y;    }};using namespace std;const int maxn = 1000010;stack<int  >S;queue<node >Q;int pp[maxn];int n,q,ecnt=0;int next[maxn*2],e[maxn*2],head[maxn];int cnt[maxn],f[maxn],x[5],y[5],other[maxn];void addedge(int u,int v){    e[ecnt]=v;    next[ecnt]=head[u];    head[u]=ecnt++;    e[ecnt]=u;    next[ecnt]=head[v];    head[v]=ecnt++;}void dfs(int u,int fa){    f[u]=fa;    S.push(u);    while (!S.empty())    {        u=S.top();        int flag=0;        for (int i=head[u];i!=-1;i=next[i])        {            int v=e[i];            if (!f[v])            {                f[v]=fa;                S.push(v);                flag=1;                break;            }        }        if (!flag)        {            S.pop();            if (!S.empty())            {                int v=u;                u=S.top();                cnt[u]=min(v,cnt[u]);                cnt[u]=min(cnt[u],cnt[v]);            }        }    }}void bfs(int u,int parent){    Q.push(node(u,parent));    while (!Q.empty())    {        int x1=n+1,x2=n+1,y1=n+1,y2=n+1;        node tem=Q.front();        Q.pop();        u=tem.u;        parent=tem.parent;        for (int i=head[u];i!=-1;i=next[i])        {            int v=e[i];            if (v!=parent)            {                Q.push(node(v,u));                int yy=min(cnt[v],v);                if (yy<y1)                {                    y2=y1;                    x2=x1;                    y1=yy;                    x1=v;                }                else if (yy<y2)                {                    y2=yy;                    x2=v;                }            }        }        for (int i=head[u];i!=-1;i=next[i])        {            int v=e[i];            if (v==u)                continue;            other[v]=other[u];            if (v!=x1)            {                other[v]=min(other[v],y1);            }            else            {                other[v]=min(other[v],y2);            }        }    }    return ;}inline void scan(int &n){    char cc;    for (; cc = getchar(), cc<'0' || cc>'9';);    n = cc - '0';    for (; cc = getchar(), cc >= '0'&&cc <= '9';)        n = n * 10 + cc - '0';}int main(){    while (scanf("%d%d",&n,&q)!=EOF)    {        int i,j,u,v,prex=0;        ecnt=0;        for (i=1;i<=n;i++)        {            head[i]=-1;            f[i]=0;            cnt[i]=n+1;            other[i]=n+1;        }        for (i=1;i<n;i++)        {//            scanf("%d%d",&u,&v);            scan(u);            scan(v);            addedge(u,v);        }        f[1]=1;        cnt[1]=n+1;        x[0]=x[1]=x[2]=0;        y[0]=y[1]=y[2]=n+1;        for (i=head[1];i!=-1;i=next[i])        {            dfs(e[i],e[i]);        }        for (i=head[1];i!=-1;i=next[i])        {            bfs(e[i],1);            int fa=min(cnt[e[i]],e[i]);            if (fa<y[0])            {                y[2]=y[1];                y[1]=y[0];                y[0]=fa;                x[2]=x[1];                x[1]=x[0];                x[0]=e[i];            }            else if (fa<y[1])            {                y[2]=y[1];                y[1]=fa;                x[2]=x[1];                x[1]=e[i];            }            else if (fa<y[2])            {                y[2]=fa;                x[2]=e[i];            }        }        for (i=2;i<=n;i++)        {            cnt[i]=min(other[i],cnt[i]);        }        for (i=0;i<q;i++)        {//            scanf("%d%d",&u,&v);            scan(u);            scan(v);            u^=prex;            v^=prex;            if (f[u]==f[v]&&(u!=1&&v!=1))            {                printf("1\n");                prex=1;            }            else            {                int tot=min(cnt[u],cnt[v]);                if (tot>y[0]&&(x[0]!=f[u]&&x[0]!=f[v]))                {                    tot=y[0];                }                else if (tot>y[1]&&(x[1]!=f[u]&&x[1]!=f[v]))                {                    tot=y[1];                }                else if (tot>y[2])                {                    tot=y[2];                }                prex=tot;                printf("%d\n",tot);            }        }    }    return 0;}


0 0
原创粉丝点击