hdu4912

来源:互联网 发布:360全景系统源码 编辑:程序博客网 时间:2024/04/30 18:07

题目大意 :给定一个棵n个节点的树,给定树上m条路径的两个端点,求最多有多少条不相交的路径(两条路径没有公共顶点即为不相交)。

基本思路:比赛时没有做出来,没想到这个路径选择有贪心性质,贪心思想比较巧妙。首先将这颗树标记层次(我习惯从小到大),然后将每条路径的两个端点的最近公共祖先(也就等于是这条路径在这个标记了层次的树中层次最高的点)求出来,再按层次权值排序(将层次值最大的排在最前面),即可用贪心。每次选取一条路径后,将这条路径中的LCA点以下的所有点标记为已访问。

#pragma comment(linker, "/STACK:1024000000,1024000000")#include<iostream>#include<cstdlib>#include<cstring>#include<cstdio>#include<vector>#include<algorithm>using namespace std;const int maxn = 100010;struct Edge{    int u,v,f,w;    Edge(){}    Edge(int x,int y,int z,int xx)    {        u=x,v=y,f=z,w=xx;    }}edges[maxn];vector<int >G[maxn];int fa[maxn][20],d[maxn];int n,m,vis[maxn],depth;bool cmp(const Edge&a,const Edge &b){    return a.w>b.w;}void dfs(int u){    for (int i=0;i<G[u].size();i++){        int v=G[u][i];        if (!d[v])        {            d[v]=d[u]+1,fa[v][0]=u;            dfs(v);            if (d[v]>depth)                depth=d[v];        }    }}void bfs (int u){    vis[u]=1;    for (int i=0;i<G[u].size();i++)    {        int v=G[u][i];        if (d[v]>d[u]&&!vis[v])        {            bfs(v);        }    }}int LCA(int p,int q){    int i,j;    if (d[p]<d[q])    {        int tem=p;        p=q;        q=tem;    }    for (i=0;(1<<i)<=d[p];i++);    for (j=i-1;j>=0;j--)    {        if (d[p]-(1<<j)>=d[q])        {            p=fa[p][j];        }    }    if (p==q)        return p;    for (j=i;j>=0;j--)    {        if (fa[p][j]!=fa[q][j])        {            p=fa[p][j];            q=fa[q][j];        }    }    return fa[p][0];}int main(){    while (scanf("%d%d",&n,&m)!=EOF)    {        int i,j,u,v,ans=0;        depth=0;        memset(fa,-1,sizeof(fa));        for (i=1;i<=n;i++){            G[i].clear();            d[i]=0;            vis[i]=0;        }        for (i=1;i<n;i++)        {            scanf("%d%d",&u,&v);            G[u].push_back(v);            G[v].push_back(u);        }        d[1]=1;        dfs(1);        for (j=1;(1<<j)<=depth;j++)        {            for (i=1;i<=n;i++)            {                int x=fa[i][j-1];                if (x!=-1)                {                    fa[i][j]=fa[x][j-1];                }            }        }        for (i=0;i<m;i++){            scanf("%d%d",&u,&v);            int f=LCA(u,v);            edges[i]=Edge(u,v,f,d[f]);        }        sort(edges,edges+m,cmp);        for (i=0;i<m;i++)        {            if (!vis[edges[i].u]&&!vis[edges[i].v])            {                if (!vis[edges[i].f])                    bfs(edges[i].f);                ans++;            }        }        printf("%d\n",ans);    }    return 0;}


0 0