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;
}
用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;
}
相关文章推荐
- HDU 4912 Paths on the tree 贪心+lca
- hdu 4912 Paths on the tree LCA + 贪心
- HDU 4912 Paths on the tree LCA 排序贪心
- hdu 4912 Paths on the tree(lca+贪心)
- hdu 4912 Paths on the tree (LCA+贪心)
- HDU_4912_Paths on the tree LCA(最近公共祖先)+贪心
- 【HDU】4912 Paths on the tree 离线LCA+贪心
- HDU4912 Paths on the tree(数据结构,lca,贪心)
- HDU 4912 - Paths on the tree (LCA 贪心)
- HDU 4912 Paths on the tree(LCA+贪心)
- HDU_4912 Path on the tree 2014多校5 贪心+LCA
- HDU 4912(Paths on the tree-树上取链,贪心)
- hdu 4912 Paths on the tree(树链剖分+贪心)
- hdu4912 Paths on the tree --- LCA贪心
- HDU 4912 Paths on the tree
- hdu 4912 Paths on the tree(lca+馋)
- HDU-4912-Paths on the tree
- hdu 4912 Paths on the tree
- hdu 4912 Paths on the tree(树链拆分+贪婪)
- [贪心+DFS序列维护树上前缀和]2014 Multi-University Training Contest 5 - 1002 Paths on the tree