邦德市
来源:互联网 发布:服务器安装centos系统 编辑:程序博客网 时间:2024/06/05 18:15
邦德市
1699(最优生成树(并查集)、LCA(倍增))
邦德市有N(编号为1..N)个城市,用M条双向道路连接,每条道路都有一个危险系数。你的任务是回答若干询问,每个询问包含一个起点s和一个终点t,要求找到一条s到t的路径,使得路径上所有边的最大危险系数最小。
第一行一个包含两个整数N和M;接下来的M行,每行包含三个整数:x,y,d(1<=x,y<=N,0<=d<=1 000 000 000),即城市x于城市y有一条危险系数为d的双向道路。下一行一个整数Q,表示有Q个询问;接下来的Q行,每行包含两个整数s,t(s!=t),表示一个询问的起点和终点。
对于每个询问,输出最优路线上所有边的危险系数的最大值。(输入数据保证所有城市是连通的)。
分析
这是一道综合性比较强的题目,反正有些知识点也忘了,干脆就直接顺带回忆
原图中每个点所关联的最小边一定是最小生成树中的边。
下面的行文风格并不是我的风格,是因为我突然抽风像这么写,但是发现并不好写
#include<stack>#include<queue>#include<cmath>#include<cstdio>#include<cstring>#include<vector>#include<iostream>#include<algorithm>using namespace std;#define oo 13//通过m计算出ooconst int maxn=10005,maxm=100005;struct edge{ int u,v,w;//最优生成树的储存结构是用的这种形式 friend bool operator<(edge a,edge b){ return a.w<b.w; }}E[maxm];int n,m,q,np;int pa[maxn];int fa[maxn][20],dep[maxn],dist[maxn][20];//倍增vector<int>gc[maxn],gw[maxn];//采取相同位置的技巧可以将j和w存在两个数组里面,因为他们位置不会改变,就用不着结构体void initial(int x){ for(int i=1;i<=n;i++) pa[i]=i;}int find(int x){ if(pa[x]==x) return x; int root=find(pa[x]); return pa[x]=root;}bool judge(int x,int y){ return find(x)==find(y);}void merge(int x,int y){ int px=find(x),py=find(y); pa[px]=py;}void Init(){ int u,v,w; scanf("%d%d",&n,&m); for(int i=1;i<=m;i++){ scanf("%d%d%d",&u,&v,&w); E[i]=(edge){u,v,w};//只用存一边即可 } sort(E+1,E+m+1); }void shengcheng(){ initial(n); int cnt=0; for(int i=1;i<=m;i++){ int x=E[i].u,y=E[i].v,w=E[i].w; if(judge(x,y))continue; cnt++; merge(x,y); gc[x].push_back(y); gc[y].push_back(x); gw[x].push_back(w); gw[y].push_back(w);//储存技巧 if(cnt==n-1) break; /*关于这个break写还是不写的问题,其实并没有什么用,时间是差不多的, 因为排序都已经是mlogm,这点算不了什么,而且cnt++本身也是需要计算时间的, 只有当m远大于n或者需要判断是否生成了树再加吧*/ }}void DFS(int i,int f,int depp,int w){ fa[i][0]=f; dep[i]=depp; dist[i][0]=w; for(int j=1;j<=oo;j++){ fa[i][j]=fa[fa[i][j-1]][j-1];//倍增顺序,现有fa才有dist dist[i][j]=max(dist[i][j-1],dist[fa[i][j-1]][j-1]); } for(int p=0;p<gc[i].size();p++){ int j=gc[i][p],w=gw[i][p]; if(j==f)continue; DFS(j,i,depp+1,w); }}int LCA(int u1,int u2){//很有技巧性 int ret=0; if(dep[u1]<dep[u2]) swap(u1,u2); int d=dep[u1]-dep[u2]; for(int j=oo;j>=0;j--){//j的顺序不能反,下面也是 if((1<<j)&d){//&这个符号不要搞忘了 ret=max(ret,dist[u1][j]);//要先改值再倍增,和生成倍增数组是不同 u1=fa[u1][j]; } } if(u1==u2) return ret;//这里要改成ret for(int j=oo;j>=0;j--){ if(fa[u1][j]!=fa[u2][j]){ ret=max(ret,dist[u1][j]); ret=max(ret,dist[u2][j]); u1=fa[u1][j]; u2=fa[u2][j]; } } return max(ret,max(dist[u1][0],dist[u2][0]));//最后还要判断一次父节点}//感觉就是回忆了一次LCA呢void out(){ for(int i=1;i<=n;i++){ cout<<i<<":"; for(int p=0;p<gc[i].size();p++){ int j=gc[i][p]; cout<<j<<" "<<gw[i][p]<<" "; } cout<<endl; }}void query(){ scanf("%d",&q); int u1,u2; while(q--){ scanf("%d%d",&u1,&u2); LCA(u1,u2); printf("%d\n",LCA(u1,u2)); }}int main(){ //freopen("in.txt","r",stdin); Init(); shengcheng(); DFS(1,0,1,0); query(); return 0;}
阅读全文
0 0
- 邦德市
- 邦德市
- C++ 邦德市
- Java基础教程23-static举例
- 湖北民族学院oj 1692(贪心) 之 木棒
- oracle 的几个函数instr(),substr(),nvl()
- Vim插件
- MFC:在CView(或CScrollView等)界面上动态添加右键菜单
- 邦德市
- 闭包与高阶函数
- 常用 Git 命令清单
- 常用的设计模式----工厂模式
- mac下使用RabbitMQ(Java语言)
- 4(1)、uboot中系统时钟初始化函数:system_clock_init
- Crnn中文end-to-end识别
- 关于jenkins自动化部署,tomcat PermGen space内存溢出处理
- Git 创建仓库