noip2013day1题解
来源:互联网 发布:linux的syslog开启 编辑:程序博客网 时间:2024/05/24 06:02
转圈游戏:
# include <iostream># include <algorithm># include <string># include <cstring># include <cmath># include <ctime># include <cstdio># include <queue>using namespace std; typedef long long ll;long long n,m,k,x; ll Read(){ll i=0,f=1;char c=getchar();whi
#include<iostream> #include<cstdio>#include<cstdlib>#include<cstring>#include<cmath>#include<algorithm>using namespace std;#define MAXN 10010#define MAXM 50010#define MAXD 22#define inf 200000int father[MAXN],n,m,q;bool visit[MAXN];int up[MAXN][MAXD],Min[MAXN][MAXD],h[MAXN];struct saver{ int s,t,d;} e[MAXM]; int cmp(saver a,saver b){ return a.d>b.d;} //并查集void init() { for(int i=0; i<MAXN; i++)father[i]=i;}int Find(int x){ if(x==father[x])return father[x]; else { father[x]=Find(father[x]); return father[x]; }}void Union(int x,int y){ int fx=Find(x); int fy=Find(y); if(fx!=fy) { father[fx]=fy; }}//处理最大生成树后的边的关系struct edge{ edge *next; int t,d; edge() { next=NULL; }}*head[MAXN];void Add(int s,int t,int d){ edge *p=new(edge); p->t=t,p->d=d,p->next=head[s]; head[s]=p;}void AddEdge(int s,int t,int d){ Add(s,t,d); Add(t,s,d);}//一个dfs过程,对于和v在一棵树上的所有结点计算其在树中的高度以及up[i][0]和Min[i][0]void BuildTree(int v){ visit[v]=true; for(edge *p=head[v]; p; p=p->next) { if(!visit[p->t]) { up[p->t][0]=v; Min[p->t][0]=p->d; h[p->t]=h[v]+1; BuildTree(p->t); } }}//得到u和v两分支高度相同的节点,在此基础上开始倍增int Move(int &v,int H){ int rec = inf; for(int i=MAXD-1; i>=0; i--) { if(h[up[v][i]]>=H) { rec=min(rec,Min[v][i]); v=up[v][i]; } } return rec;}//倍增算法实现询问u和v路径上最小值int Query(int u,int v){ if(Find(u)!=Find(v))return -1; int rec = inf; if(h[u]!=h[v])rec=h[u]>h[v]?Move(u,h[v]):Move(v,h[u]); if(u==v) return rec; for(int i=MAXD-1; i>=0; i--) { if(up[u][i]!=up[v][i]) { rec=min(rec,min(Min[u][i],Min[v][i])); u=up[u][i]; v=up[v][i]; } } rec=min(rec,min(Min[u][0],Min[v][0])); return rec;}int main(){ //输入 //freopen("truck.in", "r", stdin); //freopen("truck.out", "w", stdout); memset(head,0,sizeof(head)); memset(up,0,sizeof(up)); scanf("%d %d",&n,&m); for(int i=0; i<m; i++)scanf("%d %d %d",&e[i].s,&e[i].t,&e[i].d); //排序后生产最大生成树构成的森林 sort(e,e+m,cmp); init(); for(int i=0; i<m; i++) { if(Find(e[i].s)!=Find(e[i].t)) { Union(e[i].s,e[i].t); AddEdge(e[i].s,e[i].t,e[i].d); } } //初始化每一个结点的up[i][0]和Min[i][0],并计算结点在树中高度 memset(visit,false,sizeof(visit)); for(int i=1; i<=n; i++) { if(!visit[i]) { h[i]=0; BuildTree(i); Min[i][0]=inf; up[i][0]=i; } } //预处理出up[i][j]和Min[i][j]数组 for(int i=1; i<MAXD; i++) { for(int j=1; j<=n; j++) { up[j][i]=up[up[j][i-1]][i-1]; Min[j][i]=min(Min[j][i-1],Min[up[j][i-1]][i-1]); } } //处理询问 scanf("%d",&q); while(q--) { int u,v; scanf("%d %d",&u,&v); printf("%d\n",Query(u,v)); } return 0;}
阅读全文
0 0
- noip2013day1题解
- noip2013day1
- 【noip2013day1】【2015 10.27test】
- noip2013day1第三题 货车运输LCA+并查集
- 题解
- 题解
- 题解
- 题解
- 题解
- 题解
- 题解
- 题解
- 题解
- 题解
- 题解
- 题解~~~~
- 题解。。。。
- 题解
- [opengl笔记]2017年08月19日
- CUDA 8.0 安装
- oracle中的部分要点
- Spring之路-初识IOC
- FCN
- noip2013day1题解
- 流行编程语言的详细对比(10)--线程同步
- [Leetcode] 105, 106, 96
- 久违的总结
- python3.5安装BeautifulSoup
- mysqldump备份与还原
- JavaScript事件详解
- HTTP
- svm的c++代码编写,二维数据的硬间隔分类