hdu4912

題目大意 :給定一個棵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;
}


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章