hihoCoder 1156 彩色的树 编程之美2015初赛第一场
2015-07-16 17:17
465 查看
这一题交了十几次才过==。
首先要将无根树转化成有根树,我开始天真的以为直接按照输入序列编号从小到大指定父子关系即可,后来发现无法处理1->6,2->6的case。正解是通过DFS或者BFS遍历按序指定父子关系。
起初ans=1。当修改一个节点x的颜色时,画个图可以看粗来><
如果father[x]的颜色从相同变成不同,则会增加一颗子树。
如果father[x]的颜色从不同变成相同,则会减少一颗子树。
如果x的某个孩子tree[x][j]的颜色从相同变成不同,则会增加一颗子树。
如果x的某个孩子tree[x][j]的颜色从不同变成相同,则会减少一颗子树。
我开始用map<int,int>childcolor[i]保存第i个节点编号为a的孩子颜色是b,后来就华丽丽滴T了,其实可以用map表示
第i个颜色编号为a的孩子有b个,这样在处理孩子的时候就不需要遍历,直接相加减即可。最后还要修改map相对应的
值。
首先要将无根树转化成有根树,我开始天真的以为直接按照输入序列编号从小到大指定父子关系即可,后来发现无法处理1->6,2->6的case。正解是通过DFS或者BFS遍历按序指定父子关系。
起初ans=1。当修改一个节点x的颜色时,画个图可以看粗来><
如果father[x]的颜色从相同变成不同,则会增加一颗子树。
如果father[x]的颜色从不同变成相同,则会减少一颗子树。
如果x的某个孩子tree[x][j]的颜色从相同变成不同,则会增加一颗子树。
如果x的某个孩子tree[x][j]的颜色从不同变成相同,则会减少一颗子树。
我开始用map<int,int>childcolor[i]保存第i个节点编号为a的孩子颜色是b,后来就华丽丽滴T了,其实可以用map表示
第i个颜色编号为a的孩子有b个,这样在处理孩子的时候就不需要遍历,直接相加减即可。最后还要修改map相对应的
值。
#include<iostream> #include<stdio.h> #include<cstdio> #include<stdlib.h> #include<vector> #include<string> #include<cstring> #include<cmath> #include<algorithm> #include<stack> #include<queue> #include<ctype.h> #include<map> #include<time.h> #include<bitset> #include<set> #include<list> using namespace std; //hiho 1156 const int maxn=100005; int T; int n; int x; int y; int node[maxn]; int ans; vector<int>tree[maxn]; int father[maxn]; map<int,int>childcolor[maxn];//first is no. of color, second is no. of child with this color int rt; int q; void dfs(int nd)//brute force for small input { if(tree[nd].size()==0) { //ans++; return; } else { for(int i=0;i<tree[nd].size();i++) { int ch=tree[nd][i]; if(node[ch]!=node[nd]) { ans++; dfs(ch); } else { dfs(ch); } } } } void dfsfather(int u, int fa) { //递归转化为以u为根的子树,u的父亲为fa int d=tree[u].size(); //节点u的相邻点的个数 for(int i=0;i<d;++i) { //循环遍历跟这个节点相连接的d个节点。 int v=tree[u][i]; //节点u的第i个相邻点v if(fa!=v) { father[v]=u; childcolor[u][0]++; dfsfather(v,u); //把v的父亲节点设为u,然后递归转化为以v为根的子树 //一定要判断v是否和其父亲节点相等! } } } void solve(int x,int y) { if(node[x]==y) { return; } int fa=father[x]; // cout<<"fa: "<<fa<<endl; if(x!=rt&&node[fa]==node[x])//for internal node &&node[fa]!=y { ans++; } else if(x!=rt&&node[fa]==y) { ans-- ; } ans+=childcolor[x][node[x]]; ans-=childcolor[x][y]; childcolor[fa][node[x]]--; childcolor[fa][y]++; // cout<<ans<<" "<<childcolor[x][node[x]]<<endl; node[x]=y; } int main() { freopen("input.txt","r",stdin); // freopen("B-small-practice.in","r",stdin); // freopen("out1.txt","w",stdout); scanf("%d",&T); for(int ca=1;ca<=T;ca++) { scanf("%d",&n); memset(node,0,sizeof(node)); memset(father,0,sizeof(father)); ans=1; for(int i=0;i<=n;i++) { tree[i].clear(); childcolor[i].clear(); } for(int i=1;i<n;i++) { int u; int v; scanf("%d %d",&u,&v); tree[u].push_back(v); tree[v].push_back(u); if(i==1) { rt=min(u,v); //father[rt]=-1;会在solve()中数组下标为负数导致RE } } dfsfather(rt,-1); // queue<int> Q; //Another way to find root // Q.push(1); // while (!Q.empty()){ // int u = Q.front(); Q.pop(); // for (int i = 0; i < tree[u].size(); i++){ // int v = tree[u][i]; // if (father[u] == v) continue; // childcolor[u][0]++; // father[v] = u; // Q.push(v); // } // } scanf("%d",&q); printf("Case #%d:\n",ca); for(int i=0;i<q;i++) { int op=0; scanf("%d",&op); // cout<<i<<" op "<<op<<endl; if(op==1) { printf("%d\n",ans); } else if(op==2) { scanf("%d %d",&x,&y); solve(x,y); } } } return 0; }
相关文章推荐
- Qt5 mouseless 测试
- eclipse+maven+mybatis自动生成entity、dao层
- php -- PHP实现点击a标签的href做链接时,直接保存文件(任何类型),而不是通过浏览器直接打开下载的文件
- iOS C语言4_一维数组
- 有继承的C++析构函数一定要用virtual
- ★C++课程实训:银行储蓄系统(多文件组织)
- 中望CAD VBA检测文件是否存在
- 前台jsp控件获取java后台返回的值
- C++ static 全局变量使用注意
- 字典树的应用 单词意义查找-C语言实现
- Java构造和解析Json数据的两种方法详解二
- Java构造和解析Json数据的两种方法详解一
- Java内存管理
- Yii学习笔记(十):修改数据表中的字段后如何更新model中的字段
- C语言实现串,和简单的主函数测试
- [转]php实现粘贴截图并完成上传功能
- 极客学院java 接口与抽象类学习代码示例
- PHP实现一个简单url路由功能
- C++ 优先队列应用方法 浅析
- C# Thread Programming Start