uva 11354 bond 最小瓶颈路

来源:互联网 发布:java实验心得体会 编辑:程序博客网 时间:2024/05/01 10:43

题意:有n座城市通过m条双向道路相连,每条道路都有一个危险系数。你的任务是回答若干的询问,每个询问包含一个起点s和一个终点t,要求找到一条从s到t的路,使得途径所有边的最大危险系数最小

输出最优路线上所有边的危险系数的最大值。不同数据之间输出一个空行

给的数据很大,没法直接保存节点之间路线的危险系数的最大值。

思路是求最小生成树,然后转化成有根树,设s与t最早的公共祖先是p则s到t的路就是 s-p-t,求出s-p的危险系数最大值和p-t危险系数最大值比较即可。为了省时,首先使s和t的深度相同,就是求s-s'的危险系数最大值,然后s'和t深度相同就可以一起向上提,一直到一个公共节点。

这里一个一个向上提就太慢,所以用了类似二进制的方法,cost[i][j]指的是i节点到它上面第 2^j个祖先的危险系数最大值,因为每个长度都可以用二进制表示出来,就把s-p分成了几部分。

wa了8次,坑在重边上面

还得多练这种题

#include<cstdio>#include<cstdlib>#include<cstring>#include<iostream>#include<algorithm>#include<vector>using namespace std;typedef struct zzz{int from,to,dan;bool v;friend bool operator < (zzz a,zzz b){return a.dan<b.dan;}} Edge;Edge edge[100005];vector<int> G[50005];int n,m,p[50005][22],cost[50005][22],fa[50005],bit,father[50005];bool visit[50005];#define INF 10000000int root(int x){if(father[x]==-1) return x;return father[x]=root(father[x]);}bool merge(int a,int b){int anc_a=root(a);int anc_b=root(b);if(anc_a!=anc_b){<span style="font-family: Arial, Helvetica, sans-serif;">//并查集的确是anc_a和anc_b连起来,但实际是a和b相连</span>father[anc_a]=anc_b;G[b].push_back(a);G[a].push_back(b);return 1;}return 0;}void kruskal(){sort(edge,edge+m);for(int i=0;i<=m-1;i++){if(merge(edge[i].from,edge[i].to)) edge[i].v=1;else edge[i].v=0;}return;}void find_ancestor(){//首先求出每个节点低级的祖先,再根据低级祖先求高级祖先(先知道每个人的爸爸是谁,然后就知道每个人的爷爷是谁了)for(int i=1;(1<<i)<=n;i++)for(int j=0;j<=n-1;j++){int anc=p[j][i-1];if(anc==-1||p[anc][i-1]==-1) continue;p[j][i]=p[anc][i-1];cost[j][i]=max(cost[j][i-1],cost[anc][i-1]);}return;}void dfs(int x,int far,int father){//无根树转有根树,求每个节点的深度和父亲节点fa[x]=far;p[x][0]=father;for(vector<int>::iterator it=G[x].begin();it!=G[x].end();it++){if(!visit[*it]){visit[*it]=1;dfs(*it,far+1,x);}}return;}int solve(int node1,int node2){int differ=fa[node1]-fa[node2],ans=-INF;for(int i=bit;i>=0;i--){//将深的那个节点提到相同深度if((1<<i)<=differ){differ-=(1<<i);ans=max(ans,cost[node1][i]);node1=p[node1][i];}}for(int i=bit;i>=0;i--){//二进制,找公共祖先,但不会找到,除非一开始两个节点就重合,否则得到的是公共祖先的两个儿子节点if(p[node1][i]!=p[node2][i]){ans=max(ans,max(cost[node1][i],cost[node2][i]));node1=p[node1][i];node2=p[node2][i];}}if(node1!=node2) ans=max(ans,max(cost[node1][0],cost[node2][0]));return ans;}void init(){memset(p,-1,sizeof(p));memset(cost,0,sizeof(cost));memset(visit,0,sizeof(visit));memset(father,-1,sizeof(father));bit=0;while((1<<bit)<=n) bit++;for(int i=0;i<=n-1;i++)G[i].clear();return;}void input(){for(int i=0;i<=m-1;i++){cin>>edge[i].from>>edge[i].to>>edge[i].dan;edge[i].from--;edge[i].to--;}return;}int main(){int c=0;while(cin>>n>>m){if(c++) cout<<endl;init();input();kruskal();for(int i=0;i<=n-1;i++){//没仔细看题,不知道是不是有不连通的情况- -if(!visit[i]){visit[i]=1;dfs(i,0,-1);}}for(int i=0;i<=m-1;i++){if(edge[i].v&&p[edge[i].from][0]==edge[i].to) cost[edge[i].from][0]=edge[i].dan;if(edge[i].v&&p[edge[i].to][0]==edge[i].from) cost[edge[i].to][0]=edge[i].dan;}find_ancestor(); int q,s,t;cin>>q;while(q--){cin>>s>>t;if(fa[s-1]<fa[t-1])cout<<solve(t-1,s-1)<<endl;else cout<<solve(s-1,t-1)<<endl;}}return 0;}


0 0
原创粉丝点击