HDU 4912 Paths on the tree (LCA+贪心)

来源:互联网 发布:c语言常用代码 编辑:程序博客网 时间:2024/04/29 21:09

题目大意:给出一棵树和一些点对,要求出最多可以同时有多少点对同时存在并且路径不重复覆盖。

用tanjan的LCA求出所有点对的最近公共祖先,再按照最近公共祖先在树上的深度排序,优先选择LCA深度深的点对,然后将LCA所在的子树标记,以后不能再选。

#include <iostream>#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;const int maxn=200000+10;//树的点的两倍;struct edge{    int u,v,c,next;}e[maxn];struct Q{    int u,v,next;    int lca,no;}que[maxn];int head[maxn],cnt;int head_que[maxn],cnt_que;int n,m;int father[maxn];bool vis[maxn];//int dist[maxn];int deep[maxn];int fa[maxn];int flag[maxn],num;void add(int u,int v){    e[cnt].u=u;    e[cnt].v=v;    e[cnt].next=head[u];    head[u]=cnt++;}void add_que(int u,int v){    que[cnt_que].u=u;    que[cnt_que].v=v;    que[cnt_que].next=head_que[u];    head_que[u]=cnt_que++;}void readtree(int n){    int u,v,c;    for (int i=1;i<n;i++)        {           // scanf("%d%d%d",&u,&v,&c);           scanf("%d%d",&u,&v);            //add(u,v,c);           // add(v,u,c);           add(u,v);            add(v,u);        }}void readque(int m){    int u,v;    for (int i=0;i<m;i++)    {            scanf("%d%d",&u,&v);            if (flag[u]<flag[v])            {                add_que(v,u);            }            else add_que(u,v);            que[i].no=i;    }}void init(){    memset(head,-1,sizeof(head));    cnt=0;    memset(head_que,-1,sizeof(head_que));    cnt_que=0;}int find(int p)//并查集{    return p==father[p]?p:father[p]=find(father[p]);}void dfs(int p,int fa){    father[p]=p;    for (int i=head[p];i!=-1;i=e[i].next)    if (e[i].v!=fa)    {        dfs(e[i].v,p);        father[e[i].v]=p;    }    vis[p]=1;    for (int i=head_que[p];i!=-1;i=que[i].next)        if (vis[que[i].v])        que[i].lca=find(que[i].v);}void LCA(int root){    memset(vis,0,sizeof(vis));    memset(father,0,sizeof(father));//并查集用    dfs(root,root);}bool cmp(Q a ,Q b){    return deep[a.lca]>deep[b.lca];}void dfs_flag(int p,int fa){//cout<<"P="<<p<<endl;    for (int i=head[p];i!=-1;i=e[i].next)        if (e[i].v!=fa)        {            dfs_flag(e[i].v,p);           // cout<<"P="<<p<<endl;        }        flag[p]=num++;}//void dfs_dist(int p,int fa)//{//    for (int i=head[p];i!=-1;i=e[i].next)//        if (e[i].v!=fa)//        {//            dist[e[i].v]=dist[p]+e[i].c;//            dfs_dist(e[i].v,p);//        }//}void dfs_deep(int p){    for (int i=head[p];i!=-1;i=e[i].next)        if (e[i].v!=fa[p])    {        fa[e[i].v]=p;        deep[e[i].v]=deep[p]+1;        dfs_deep(e[i].v);    }}void dfs_vis(int p){    vis[p]=1;    for (int i=head[p];i!=-1;i=e[i].next)        if (e[i].v!=fa[p]&&!vis[e[i].v])    {        dfs_vis(e[i].v);    }}int main(){    freopen("in.txt","r",stdin);    int T;    //scanf("%d",&T);   // cout<<T<<endl;    //while (T--)    while (~scanf("%d%d",&n,&m))    {        //cout<<T<<endl;        int root=1;        init();       // scanf("%d%d",&n,&m);        readtree(n);//读入n个点的树;       // cnt=0;        num=0;        dfs_flag(root,-1);//对树按照左右根标号;        readque(m);//读入m个询问;        LCA(1);//LCA        deep[root]=1;        fa[root]=root;        dfs_deep(root);        sort(que,que+m,cmp);       // dist[root]=0;       // dfs_dist(root,-1);        int ans=0;        memset(vis,0,sizeof(vis));        for (int i=0;i<m;i++)            if (!vis[que[i].u]&&!vis[que[i].v])                {                    dfs_vis(que[i].lca);                    ans++;                }            cout<<ans<<endl;//        for (int i=0;i<m;i++)//            cout<<dist[que[i].u]+dist[que[i].v]-2*dist[que[i].lca]<<endl;    }    return 0;}


0 0
原创粉丝点击