L2-001 紧急救援
作者:互联网
L2-001 紧急救援
这道题感觉就是dijstra模板题做了小改动,需要处理所有最短路径,然后记录所有路径和点权和最大的那条,我的处理比较直观(bushi,蠢),比较高明的做法:
我们没必要记录所有最短路经的信息,只需要记录点权最大的那条,但遇到路径长度相等的时候要记录到该点最短路径的条数,在发现相同最短路径的时候更新点权最大的路径
被卡住的地方:当发现更短路径的时候,要直接更新点权最大的路径信息,因为点权最大的路径是从最短路径中选的
rubbish code:
#include<stdio.h>
#include<iostream>
#include<stdlib.h>
#include<stack>
#include<vector>
#define LOCAL
using namespace std;
typedef long long int ll;
/*
题目要求从所有最短路径中选取召集的救援队最多的那条
然后输出最短路径的条数,最多救援队数量,以及 该路径途经城市(包括起始)
具体思路:
用djstra来搞,记录每个点的pre,查路径倒着查
*/
int read(){
int s=0,f=1,c=getchar();
while (c<'0' || c>'9') { if (c=='-') f=-1; c=getchar();}
while (c>='0' && c<='9') {s=(s<<3)+(s<<1)+c-'0';c=getchar();}
return s*f;
}
const int maxn=505;
const int INF=255000;
int dis[maxn][maxn];
int num[maxn];
bool mark[maxn]={0};
vector<int> pre[maxn];
int mm[maxn];
int mpre[maxn];//记录到该点的最短路径中救援队最多的那条的前置点(题目中已经说了最优解唯一)
int n,m,s,d;
void djstra(){
int stk[n+5];
int top=0;
mark[s]=1;
while (1){
int mind=INF;
int flag=0;
for (int i=0;i<n;++i){
if (mark[i]) continue;
flag=1;
if (dis[s][i]<mind ){
mind=dis[s][i];
top=0;
stk[top++]=i;
}
else if (dis[s][i]==mind) stk[top++]=i;
}
for (int i=0;i<top;++i){
mark[stk[i]]=1;
// cout<<stk[i]<<endl;
}
if (flag==0) break;
for (int i=0;i<n;++i){
if (mark[i]) continue;
for (int j=0;j<top;++j){
// cout<<stk[j]<<endl;
// dis[s][i]=min(dis[s][i],dis[s][stk[j]]+dis[stk[j]][i]);
if (dis[s][i]>dis[s][stk[j]]+dis[stk[j]][i]){
dis[s][i]=dis[s][stk[j]]+dis[stk[j]][i];
pre[i].clear();
pre[i].push_back(stk[j]);
// if (mm[i]<mm[stk[j]]+num[i]){
mm[i]=mm[stk[j]]+num[i];
mpre[i]=stk[j];
// }
}
else if (dis[s][i]==dis[s][stk[j]]+dis[stk[j]][i]){
// cout<<stk[j]<<endl;
if (mm[i]<mm[stk[j]]+num[i]){
mm[i]=mm[stk[j]]+num[i];
mpre[i]=stk[j];
}
pre[i].push_back(stk[j]);
}
}
}
// cout<<__LINE__<<endl;
top=0;
}
}
int dfs(int p){
if (p==s) return 1;
int sum=0,len=(int)pre[p].size();
for (int i=0;i<len;++i){
// cout<<pre[p][i]<<endl;
sum+=dfs(pre[p][i]);
}
return sum;
}
int main(){
#ifdef LOCAL
freopen("input.txt","r",stdin);
#endif
n=read(),m=read(),s=read(),d=read();
for (int i=0;i<n;++i){
pre[i].push_back(s);
mpre[i]=s;
num[i]=read();
mm[i]=i==s?num[s]:(num[s]+num[i]);
for (int j=i+1;j<n;++j) {
dis[i][j]=dis[j][i]=INF;
}
}
// cout<<__LINE__<<endl;
for (int i=0;i<m;++i){
int u=read(),v=read(),w=read();
dis[u][v]=min(dis[u][v],w);
dis[v][u]=dis[u][v];
// cout<<__LINE__<<endl;
}
djstra();
// for (int i=0;i<n;++i){
// for (int j=0;j<(int)pre[i].size();++j){
// cout<<pre[i][j]<<" ";
// }
// cout<<endl;
// }
int res=dfs(d);
printf("%d %d\n",res,mm[d]);
// int cont=0;
int pp=d;
stack<int> tmp;
while (pp!=s){
// cont++;
// printf("%d ",pp);
tmp.push(pp);
pp=mpre[pp];
}
// printf("%d %d\n",cont,mm[d]);
printf("%d",s);
while (!tmp.empty()){
int t=tmp.top();
tmp.pop();
printf(" %d",t);
}
return 0;
}
标签:tmp,救援,int,点权,路径,stk,001,L2,include 来源: https://www.cnblogs.com/DarrenLU/p/16066252.html