CSU 1811 Tree Intersection(启发式合并)
2016-09-05 20:03
344 查看
今天学了好多新知识呀喵喵喵
启发式合并,其实只是一种思想,就是在一些交换的时候,按照大小的顺序,把小的往大的上加
这样的复杂度是对于合并出来n个东西,是O(nlogn)的
为什么呢,最坏情况下是操作了
n2+2∗n4+4∗n8+⋯≤n2+n3+n4+⋯=nlogn
然后对于一棵树,如果每个子节点都有一个信息,并且信息的种类很多,不好记录
那么可以直接用map对每个子树的信息进行记录,然后回溯上去的时候
父节点加上子节点信息的时候,把小的往大的加
然后每次新出来一个颜色,就+1,如果颜色满了,就−1
每次新搜一个节点的时候,如果子节点更大,那么ans也要赋值成子节点的ans
想一下就知道了,知道启发式合并之后,难点就是ans的变化了
代码:
启发式合并,其实只是一种思想,就是在一些交换的时候,按照大小的顺序,把小的往大的上加
这样的复杂度是对于合并出来n个东西,是O(nlogn)的
为什么呢,最坏情况下是操作了
n2+2∗n4+4∗n8+⋯≤n2+n3+n4+⋯=nlogn
然后对于一棵树,如果每个子节点都有一个信息,并且信息的种类很多,不好记录
那么可以直接用map对每个子树的信息进行记录,然后回溯上去的时候
父节点加上子节点信息的时候,把小的往大的加
然后每次新出来一个颜色,就+1,如果颜色满了,就−1
每次新搜一个节点的时候,如果子节点更大,那么ans也要赋值成子节点的ans
想一下就知道了,知道启发式合并之后,难点就是ans的变化了
代码:
#include <map> #include <set> #include <stack> #include <queue> #include <cmath> #include <string> #include <vector> #include <cstdio> #include <cctype> #include <cstring> #include <sstream> #include <cstdlib> #include <iostream> #include <algorithm> #pragma comment(linker,"/STACK:102400000,102400000") using namespace std; #define MAX 100005 #define MAXN 1000005 #define maxnode 205 #define sigma_size 2 #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 #define lrt rt<<1 #define rrt rt<<1|1 #define middle int m=(r+l)>>1 #define LL long long #define ull unsigned long long #define mem(x,v) memset(x,v,sizeof(x)) #define lowbit(x) (x&-x) #define pii pair<int,int> #define bits(a) __builtin_popcount(a) #define mk make_pair #define limit 10000 //const int prime = 999983; const int INF = 0x3f3f3f3f; const LL INFF = 0x3f3f; //const double pi = acos(-1.0); const double inf = 1e18; const double eps = 1e-9; const LL mod = 1e9+7; const ull mx = 133333331; /*****************************************************/ inline void RI(int &x) { char c; while((c=getchar())<'0' || c>'9'); x=c-'0'; while((c=getchar())>='0' && c<='9') x=(x<<3)+(x<<1)+c-'0'; } /*****************************************************/ struct Edge{ int v,next,id; }edge[MAX*2]; int head[MAX]; int ans[MAX]; int sum[MAX]; int c[MAX]; map<int,int> cnt[MAX]; int tot; void init(){ mem(head,-1); mem(ans,0); mem(sum,0); tot=0; } void add_edge(int a,int b,int id){ edge[tot]=(Edge){b,head[a],id}; head[a]=tot++; } void dfs(int u,int fa,int id){ cnt[u][c[u]]=1; if(sum[c[u]]>1) ans[id]++; for(int i=head[u];i!=-1;i=edge[i].next){ int v=edge[i].v; if(v==fa) continue; dfs(v,u,edge[i].id); if(cnt[u].size()<cnt[v].size()){ swap(cnt[u],cnt[v]); ans[id]=ans[edge[i].id]; } for(map<int,int>::iterator it=cnt[v].begin();it!=cnt[v].end();it++){ int x=it->first,y=it->second; if(cnt[u].count(x)){ cnt[u][x]+=y; if(cnt[u][x]==sum[x]) ans[id]--; } else{ cnt[u][x]=y; if(cnt[u][x]<sum[x]) ans[id]++; } } } } int main(){ //freopen("in.txt","r",stdin); int n; while(cin>>n){ init(); for(int i=1;i<=n;i++){ scanf("%d",&c[i]); cnt[i].clear(); sum[c[i]]++; } //cout<<all<<endl; for(int i=1;i<n;i++){ int a,b; scanf("%d%d",&a,&b); add_edge(a,b,i); add_edge(b,a,i); } dfs(1,-1,0); for(int i=1;i<n;i++) printf("%d\n",ans[i]); } return 0; }
相关文章推荐
- 正则表达式
- 一道留学作业题//C语言
- Unity 优化
- 图算法(1) - 基础知识
- PAT(乙级)1013 组个最小数 (20)
- Lightoj1202——Bishops(找规律)
- 友盟分享遇到的坑
- EnterpriseLibrary 6.0中DAAB独立数据库配置文件初始化
- 13_CXF和Spring整合发布服务
- 16.9.5 C组第二题:3055
- 在通过hibernate进行删除操作时遇到的一个异常
- PyCHarm使用教程
- 基于python开发hadoop shell
- 有道云笔记网页剪报(备)
- Hellow Java!
- java实现在同一Excel文件上写数据
- 第二周项目1-C/C++语言中函数参数传递的三种方式
- LFCS 系列第十四讲: Linux 进程资源用量监控和按用户设置进程限制
- leetcode Submission Details
- 关于使用BootStrap按钮组件无法显示其底色的问题总结