Dijkstra专题
Public Bike Management (30)
卡了半天原来是看漏了这句话:If there are more than one shortest path, the one that requires the least number of bikes sent from PBMC will be chosen.
最后输出描述中也有一句:Note that if such a path is not unique, output the one that requires minimum number of bikes that we must take back to PBMC.
因此是要先满足sendTo
最小,其次才是takeBack
。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
using namespace std;
const int N=510;
const int PBMC=0;
const int INF=0x3f3f3f3f;
int cmax,n,sp,m;
int c[N],g[N][N],dis[N];
bool vis[N];
vector<int>pre[N];
vector<int>tmpPath,bestPath(N);
int bestTake=INF,bestSend=INF;
void Dijkstra(){
memset(dis,63,sizeof(dis));
memset(vis,false,sizeof(vis));
dis[0]=0;
for(int i=1;i<=n;++i){
int u=-1,minv=INF;
for(int j=0;j<=n;++j)
if(!vis[j]&&dis[j]<minv){
u=j;
minv=dis[j];
}
if(u==-1) break;
vis[u]=true;
for(int i=1;i<=n;++i)
if(!vis[i]&&g[u][i]<INF){
if(dis[i]>dis[u]+g[u][i]){
dis[i]=dis[u]+g[u][i];
pre[i].clear();
pre[i].push_back(u);
}else if(dis[i]==dis[u]+g[u][i])
pre[i].push_back(u);
}
}
}
void DFS(int v){
tmpPath.push_back(v);
if(v==PBMC){
int sendTo=0,takeBack=0;
//注意tmpPath[tmpPath.size()-1]==PBMC,默认是0,如果从这里开始就会让send变大
for(int i=tmpPath.size()-2;i>=0;--i){
if(c[tmpPath[i]]<cmax){
int tmpSend=cmax-c[tmpPath[i]];
if(tmpSend<=takeBack) {
takeBack-=tmpSend;
continue;
}else tmpSend-=takeBack,takeBack=0;
sendTo+=tmpSend;
}
else takeBack+=c[tmpPath[i]]-cmax;
}
if(sendTo<bestSend){
bestSend=sendTo;
bestTake=takeBack;
bestPath=tmpPath;
}else if(sendTo==bestSend&&takeBack<bestTake){
bestTake=takeBack;
bestPath=tmpPath;
}
}else{
for(int i=0;i<pre[v].size();++i)
DFS(pre[v][i]);
}
tmpPath.pop_back();
}
int main() {
scanf("%d%d%d%d",&cmax,&n,&sp,&m);
cmax>>=1;
memset(g,INF,sizeof(g));
for(int i=1;i<=n;++i)
scanf("%d",&c[i]);
for(int i=1;i<=m;++i){
int s1,s2,t;
scanf("%d%d%d",&s1,&s2,&t);
g[s1][s2]=g[s2][s1]=t;
}
Dijkstra();
DFS(sp);
printf("%d ",bestSend);
for(int i=bestPath.size()-1;i>=1;--i)
printf("%d->",bestPath[i]);
printf("%d ",bestPath[0]);
printf("%d\n",bestTake);
return 0;
}
All Roads Lead to Rome (30)
和上一题属于同一类题型,都是用 Dijkstra 算法求最短路径,而且需要通过记录前驱节点来遍历所有最短路径。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <algorithm>
#include <string>
#include <string.h>
#include <vector>
using namespace std;
const int N=210;
const int MAXN=26*26*26;
const int INF=0x3f3f3f3f;
int n,k;
int startCity,endCity;
int mapIndex[MAXN],revMapIndex[N];
int happy[N],g[N][N],dis[N];
bool vis[N];
vector<int>pre[N];
vector<int>tmpPath,bestPath(N);
int bestHappy,bestCount=INF,bestRoutes;
inline int toNumber(char *name){
return (name[0]-'A')*26*26+(name[1]-'A')*26+(name[2]-'A');
}
inline void toCString(int num){
num=revMapIndex[num];
char name[4];
name[2]=(num%26)+'A';
num/=26;
name[1]=(num%26)+'A';
num/=26;
name[0]=(num%26)+'A';
printf("%c%c%c",name[0],name[1],name[2]);
}
void Dijkstra(){
memset(dis,63,sizeof(dis));
memset(vis,false,sizeof(vis));
dis[startCity]=0;
for(int i=1;i<=n;++i){
int u=-1,minv=INF;
for(int j=1;j<=n;++j)
if(!vis[j]&&dis[j]<minv){
u=j;
minv=dis[j];
}
if(u==-1) break;
vis[u]=true;
for(int j=1;j<=n;++j)
if(!vis[j]&&g[u][j]<INF){
if(dis[j]>dis[u]+g[u][j]){
dis[j]=dis[u]+g[u][j];
pre[j].clear();
pre[j].push_back(u);
}else if(dis[j]==dis[u]+g[u][j])
pre[j].push_back(u);
}
}
}
void DFS(int v){
tmpPath.push_back(v);
if(v==startCity){
bestRoutes++;
int cur=0;
for(int i=tmpPath.size()-2;i>=0;--i){
cur+=happy[tmpPath[i]];
}
if(cur>bestHappy){
bestHappy=cur;
bestCount=tmpPath.size();
bestPath=tmpPath;
}else if(cur==bestHappy&&tmpPath.size()<bestCount){
bestCount=tmpPath.size();
bestPath=tmpPath;
}
}else{
for(int i=0;i<pre[v].size();++i)
DFS(pre[v][i]);
}
tmpPath.pop_back();
}
int main() {
char name1[5],name2[5]="ROM";
scanf("%d%d%s",&n,&k,name1);
startCity=toNumber(name1);
endCity=toNumber(name2);
mapIndex[startCity]=1;
revMapIndex[1]=startCity;
memset(g,INF,sizeof(g));
for(int i=2;i<=n;++i){
scanf("%s",name1);
int s=toNumber(name1);
mapIndex[s]=i;
revMapIndex[i]=s;
scanf("%d",&happy[i]);
}
startCity=mapIndex[startCity];
endCity=mapIndex[endCity];
for(int i=1;i<=k;++i){
scanf("%s %s",name1,name2);
int s1=mapIndex[toNumber(name1)],s2=mapIndex[toNumber(name2)];
scanf("%d",&g[s1][s2]);
g[s2][s1]=g[s1][s2];
}
Dijkstra();
DFS(endCity);
printf("%d %d %d %d\n",bestRoutes,dis[endCity],bestHappy,bestHappy/(bestCount-1));
for(int i=bestPath.size()-1;i>=1;--i){
toCString(bestPath[i]);
printf("->");
}
toCString(bestPath[0]);
printf("\n");
return 0;
}