HDU6203 补题LCA复习+dfs序

来源:互联网 发布:电气接线仿真软件 编辑:程序博客网 时间:2024/05/21 07:07

这个题目其实算是贪心吧,感觉自己贪心有点菜,这几天要把贪心练一下了

建树,dfs什么的就不说了,这里主要讲下思路

就是建完树后,给你两个点

然后求出他们的lca,将这两个点u,v和lca,dlca(lca点的深度)存在一个结构体数组中

然后将这个数组按深度从大到小排序

接着遍历这个数组

每次看u,v有没有访问过,如果有就不管,如果没有,就将他们的lca点拿掉并将lca点的所有子节点记为访问过并且ans++

最后输出ans就好了

其实,为什么这样做可以呢

对于一个u,v,我们要做的就是把他们分开,我们就可以拿掉链接u,v上的点的任意一个就好,那么就会出现一个问题

如果有另外两个点的lca正好经过这一条链,那么如果我只拿掉那个点的lca就好了

如果我们这样排序的话,其实就保证了这种情况,也就是保证了最优

还有一点,我们标记已访问过的点时,不需要用到树链剖分,因为是对子树的操作,dfs序就可以了

这个题目有点手残,用的线段树求的lca,代码量直接爆炸了


#include <iostream>#include <cstring>#include <cstdio>#include <cstring>#include <algorithm>#define maxn 60010using namespace std;struct Edge{    int next,en;};struct Save{    int node,dep;    Save(int n,int d){node=n;dep=d;}    Save(){}};bool operator < (Save a,Save b){return a.dep<b.dep;}struct Node{    int u,v;    Save lca;};bool operator < (Node a,Node b){return a.lca.dep<b.lca.dep;}bool cmp(Node a,Node b){return a.lca.dep>b.lca.dep;}Edge edge[maxn];Node node[maxn];Save save[maxn*2];Save segt[maxn<<2];//线段树的大小为节点大小的4倍int head[maxn],cnte;int dfsx,in[maxn],out[maxn],vis[maxn],cntn;int LCAArray[maxn*2];void init(){    memset(head,-1,sizeof(head));    memset(vis,0,sizeof(vis));    cnte=0;cntn=0;dfsx=0;}void addedge(int st,int en){    cnte++;    edge[cnte].en=en;    edge[cnte].next=head[st];    head[st]=cnte;    return;}void addnode(int u,int v,Save lca){    cntn++;    node[cntn].u=u;node[cntn].v=v;    node[cntn].lca=lca;    return;}void dfs(int root,int depth)//dfs没问题{    dfsx++;    in[root]=dfsx;vis[root]=1;    save[dfsx].dep=depth;save[dfsx].node=root;    for (int k=head[root];k!=-1;k=edge[k].next)        if (!vis[edge[k].en])        {            dfs(edge[k].en,depth+1);            dfsx++;            save[dfsx].dep=depth;save[dfsx].node=root;        }    out[root]=dfsx;    return;}void build(int root,int beg,int en)//线段树建树函数{    if (beg==en)        segt[root]=save[beg];    else    {        build(root*2,beg,(beg+en)/2);        build(root*2+1,(beg+en)/2+1,en);        if (segt[root*2]<segt[root*2+1])            segt[root]=segt[root*2];        else segt[root]=segt[root*2+1];    }    return;}Save query(int root,int l,int r,int ql,int qr){    if(l == ql && r == qr) return segt[root];    int mid=(l+r)/2;    if(qr <= mid) return query(root*2,l,mid,ql,qr);    else if(ql >= mid + 1) return query(root*2+1,mid+1,r,ql,qr);    return min(query(root*2,l,mid,ql,mid), query(root*2+1,mid + 1,r,mid + 1,qr));}void initLCA(int n){    dfs(0,1);    build(1,1,dfsx);}Save LCA(int u,int v){    int qbeg,qend;    if (in[u]<in[v])    {qbeg=in[u];qend=in[v];}    else    {qbeg=in[v];qend=in[u];}    return query(1,1,dfsx,qbeg,qend);}struct Segt{    int val,addmark;};Segt segtf[maxn<<2];void pushdown(int root){    if (segtf[root].addmark!=0)    {        segtf[root*2].val+=segtf[root].addmark;        segtf[root*2].addmark+=segtf[root].addmark;        segtf[root*2+1].val+=segtf[root].addmark;        segtf[root*2+1].addmark+=segtf[root].addmark;        segtf[root].addmark=0;    }    return;}int queryf(int root,int l,int r,int poi){    if(l==r) return segtf[root].val;    pushdown(root);    int mid=(l+r)/2;    if(poi <= mid) return queryf(root*2,l,mid,poi);    else if(poi >= mid + 1) return queryf(root*2+1,mid+1,r,poi);}void updatef(int root,int rst,int ren,int beg,int en,int val){    if (rst>=beg&&ren<=en)    {        segtf[root].val+=val;        segtf[root].addmark+=val;    }    else if (rst>en||ren<beg) {return;}    else    {        pushdown(root);        int mid=(rst+ren)/2;        updatef(root*2,rst,mid,beg,en,val);        updatef(root*2+1,mid+1,ren,beg,en,val);        segtf[root].val=segtf[root*2].val&&segtf[root*2+1].val;    }}int main(){    int n,m;    while(~scanf("%d",&n))    {        init();        for (int k=1;k<=n;k++)        {            int st,en;            scanf("%d %d",&st,&en);            addedge(st,en);addedge(en,st);        }        n++;        initLCA(n);        scanf("%d",&m);        for (int k=1;k<=m;k++)        {            int u,v;            Save lca;            scanf("%d %d",&u,&v);            lca=LCA(u,v);            addnode(u,v,lca);        }        sort(node+1,node+1+cntn,cmp);        memset(segtf,0,sizeof(segtf));        int ans(0);        for (int k=1;k<=cntn;k++)        {            int u,v,l;            u=node[k].u;v=node[k].v;l=node[k].lca.node;            if ((queryf(1,1,dfsx,in[u])==0)&&(queryf(1,1,dfsx,in[v])==0))            {                ans++;                updatef(1,1,dfsx,in[l],out[l],1);            }        }        printf("%d\n",ans);    }    return 0;}


原创粉丝点击