营救——kruskal、dijksta
P1396 营救 - 洛谷 | 计算机科学教育新生态 (luogu.com.cn)
这道题刚开始题都没读懂。。。。题说的是求经过的每条大道所代表的拥挤度最大值的最小值。说出来感觉很绕,其实就是要从目的地到终点的过程中,求大道拥挤度的最大值k,因为有不同的走法,所以求不同走法中k的最小值。
两种方法,最短路和最小生成树都可以。
1.最短路
可以用dijkstra堆优化,也可以用其他的。这里我用堆优化的dijkstra。
本来的板子是求从起点到终点的最短距离。但是,我们要求的答案不一定在最短距离中出现。所以需要做一点改动。
可以思考一下,因为求的是每种走法的大道拥挤度最大值k的最小值,因此我们可以在板子中不再将距离求和,而是判断该点的拥挤度最大值是多少。因为该点的拥挤度最大应该是该点的临近点的拥挤度最大值与这两点的边权取最大值k。所以我们把求和的式子改成求max的式子。如果k小于其他走法的该点最大值,那么该点最大值的最小值就是k。
这样一代一代传下去,结果就是路程中拥挤度最大值的最小值了!
注意这是无向图,add要加两遍哦。
1 #include <bits/stdc++.h> 2 using namespace std; 3 const int N=1e4+100,M=4e4+100; 4 int dist[N],st[N],h[N]; 5 int n,m,s,t,idx; 6 7 struct node 8 { 9 int ne,now,w; 10 }e[M]; 11 12 void add(int x,int y,int w) 13 { 14 idx++; 15 e[idx].ne=h[x];e[idx].now=y;e[idx].w=w; 16 h[x]=idx; 17 } 18 typedef pair<int,int> pii; 19 priority_queue<pii,vector<pii>,greater<pii> >q; 20 void dijkstra() 21 { 22 memset(dist,0x3f,sizeof dist); 23 dist[s]=0; 24 q.push({0,s}); 25 while(q.size()) 26 { 27 pii sta=q.top();q.pop(); 28 int x=sta.second; 29 if(st[x])continue; 30 st[x]=1; 31 for(int i=h[x];i;i=e[i].ne) 32 { 33 int y=e[i].now; 34 int k=max(dist[x],e[i].w); 35 if(dist[y]>k) 36 { 37 dist[y]=k; 38 q.push({dist[y],y}); 39 } 40 } 41 } 42 printf("%d\n",dist[t]); 43 } 44 45 int main() 46 { 47 scanf("%d%d%d%d",&n,&m,&s,&t); 48 while(m--) 49 { 50 int u,v,w; 51 scanf("%d%d%d",&u,&v,&w); 52 add(u,v,w); 53 add(v,u,w); 54 } 55 56 dijkstra(); 57 58 59 return 0; 60 }
2.最小生成树
用kruskal算法做。
因为克鲁斯卡尔算法已经把边权从小到大排好序了,所以当起点和终点第一次出现在同一个连通块的时候,那个边权就是拥挤度最大值的最小值,再进行for的话,边权就不再是拥挤度最大值的最小值了。所以直接在for中判断是否起点终点在同一连通块,在的话就结束循环,输出此时的边权。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n,m,s,t,a[20001]; 4 struct each 5 { 6 int x,y,cost; 7 }b[20001];//存边 8 bool com(each x,each y) 9 { 10 return x.cost<y.cost; 11 } 12 int read()//读入优化模板 13 { 14 char ch=getchar(); 15 int x=0,f=1; 16 while(ch<'0'||ch>'9') 17 { 18 if(ch=='-') 19 f=-1; 20 ch=getchar(); 21 } 22 while(ch>='0'&&ch<='9') 23 { 24 x=x*10+ch-'0'; 25 ch=getchar(); 26 } 27 return x*f; 28 } 29 int find(int x)//并查集基本操作 30 { 31 if(a[x]==0) 32 return x; 33 a[x]=find(a[x]); 34 return a[x]; 35 } 36 int main() 37 { 38 n=read(); 39 m=read(); 40 s=read(); 41 t=read(); 42 for(int i=1;i<=m;i++)//无脑输入 43 { 44 b[i].x=read(); 45 b[i].y=read(); 46 b[i].cost=read(); 47 } 48 sort(b+1,b+m+1,com);//排序 49 for(int i=1;i<=m;i++)//克鲁斯卡尔最小生成树连边 50 { 51 int X=find(b[i].x),Y=find(b[i].y); 52 if(X!=Y) 53 a[X]=Y; 54 if(find(s)==find(t))//如果联通直接输出退出 55 { 56 cout<<b[i].cost<<endl; 57 return 0; 58 } 59 } 60 return 0; 61 }

浙公网安备 33010602011771号