codeforces 455C Civilization 树的最长链+并查集
来源:互联网 发布:淘宝男迷彩加绒衫 编辑:程序博客网 时间:2024/05/21 11:18
题意:
给定n个城市和m个道路,在同一个连通块的城市为一个区域。
有两个操作,第一个操作:询问第x个城市所在的区域最长链是多少。第二个操作:将第x个城市所在的区域和第y个城市所在的区域相连接,要求连接后的最长链最短。
思路:
先来考虑第一个操作,求连通域内最长链可用两次dfs,然后我们记录下最长链中间的结点,令len[u][0]和len[u][1]分别为最长链左边的长度和右边的长度,然后将其余结点的根节点设改该结点,用并查集,则每次查询只用找到询问结点的根结点即可。
第二个操作则,若要求连接后的最长链最短,则一定是将两个区域的根结点相连,相连之后令一个区域根节点为另一个区域根节点,更新len[u][0]和len[u][1],具体更新看代码。
#include<cstdio>#include<cstring>#include<algorithm>#include<vector>#define mem(name,value) memset(name,value,sizeof(name))#define FOR(i,n) for(int i=1;i<=n;i++)using namespace std;const int maxn = 3*100000+10;int path[maxn],len[maxn][2],p[maxn];int path_max,path_start,path_mid;bool vis[maxn];vector<int>G[maxn];void dfs1(int s,int cur,int f){ //第一次dfs找到最长链的起点 if(cur>=path_max){ path_max = cur; path_start = s; } for(int i=0;i<G[s].size();i++) if(G[s][i]!=f) dfs1(G[s][i],cur+1,s);}void dfs2(int s,int cur,int f){//第二次dfs算出最长链和找到最长链的中间结点 path[cur]=s; if(cur>=path_max){ path_max = cur; path_mid = path[cur/2]; } for(int i=0;i<G[s].size();i++) if(G[s][i]!=f) dfs2(G[s][i],cur+1,s);}void dfs3(int s,int f){ //第三次dfs将其余点都设为该结点的子节点,并标记所有访问过的结点 vis[s]=true; p[s] = path_mid; for(int i=0;i<G[s].size();i++) if(G[s][i]!=f) dfs3(G[s][i],s);}int find_set(int x){return p[x]==x ? x : p[x]=find_set(p[x]);}void merge_set(int a,int b){ int x = find_set(a), y = find_set(b); if(x==y) return ; int x1 = max(len[x][0],len[x][1]); int y1 = max(len[y][0],len[y][1]); if(x1<y1) swap(x,y); p[y] = x; x1 = max(len[x][0],len[x][1]); y1 = max( min(len[x][0],len[x][1]),max(len[y][0],len[y][1])+1 ); len[x][0] = x1; len[x][1] = y1;}int main(){ //freopen("in.txt","r",stdin); int n,m,q,tmp,x,y; scanf("%d%d%d",&n,&m,&q); for(int i=0;i<m;i++){ scanf("%d%d",&x,&y); G[x].push_back(y); G[y].push_back(x); } mem(vis,false); mem(len,0); for(int i=1;i<=n;i++){ if(!vis[i]){ path_max = 0; dfs1(i,0,-1); dfs2(path_start,0,-1); dfs3(path_mid,-1); len[path_mid][0]=path_max / 2; len[path_mid][1] = path_max - len[path_mid][0]; } } for(int i=0;i<q;i++){ scanf("%d",&tmp); if(tmp==1){ scanf("%d",&x); tmp = find_set(x); printf("%d\n",len[tmp][0]+len[tmp][1]); }else{ scanf("%d%d",&x,&y); merge_set(x,y); } } return 0;}
0 0
- codeforces 455C Civilization 树的最长链+并查集
- Codeforces 455C Civilization 树的直径+并查集
- 【树的直径+并查集】 codeforces 455C - Civilization
- Codeforces 455C —— Civilization(并查集,树上最长链)
- CodeForces 455C Civilization(并查集+树直径)
- codeforces 455C C. Civilization(树形dp+树的直径+并查集)
- Codeforces 455C. Civilization (树的直径+并查集)
- 【CodeForces】445C Civilization 并查集
- Codeforces 455C Civilization(并查集+dfs)
- Codeforces 455C Civilization(并查集+dfs)
- Codeforces 455C Civilization(并查集+树形dp)
- 【打CF,学算法——四星级】CodeForces 455C Civilization (【详解】并查集+树的直径)
- Codeforces 455E Civilization【思维+树的直径+并查集】
- codeforces 466C Civilization 并查集+dfs
- codeforces round260 div1C&div2E Civilization 并查集+树的直径
- codeforces 455C Civilization
- CodeForces 455C-Civilization
- CodeForces 455C Civilization
- hdu 3257 Hello World!(位运算 & 模拟)
- IOS日志记录
- Android——AsyncTask
- 【时尚】身份证上的X到底代表什么
- 如何获取openstack nova各版本源码
- codeforces 455C Civilization 树的最长链+并查集
- s 参数 快速 记忆法
- codeforces 149D - Coloring Brackets (区间dp)
- c++中头文件与实现文件的关系
- 《分布式操作系统》知识点(1~7)一
- broadcastreceiver使用注意(一)
- POJ2739 Sum of Consecutive Prime Numbers素数打表
- XDOJ1012--奇妙的旅行
- ZXing 2.2 扫描框竖屏修改