您的位置:首页 > 其它

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

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

用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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  LCA