解题报告:
由于顶点(城镇)的数目只有200个,所以可以采用邻接矩阵的形式来存储,代码会更简洁些,也不容易出错。但是处于练习的目的,采用邻接表+优先队列的方式实现,优先队列使用STL中的priority_queue。很基础的单源单汇最短路径。
解题报告:
基本和1874是一样的,只是数据量小了,并且要求当n==0 && m==0时终止,值得注意!这道题同时也保证了一定是可达的,所以输出时可以直接输出。
解题报告:
这是一道多源多汇的最短路径问题,要新增一个统一的虚源,记为0(其实就是看成是草儿的家),并且0和其它源的距离都是0,这样就完成了转化。值得注意的是,输入数据是有重边的,如果用邻接矩阵做,要比较去重,邻接表的话,直接做就是了!
解题报告:
看完题目直接笑喷了,能不要这么逗么!!!其实这题也就是要处理下字符串而已,直接用map映射成整数,映射完后,就跟2544和1874是一样的了。唯一值得注意的就是:start和end是可能一样的!
/// HDU 1874 邻接表+优先队列
#include<iostream>
#include<vector>
#include<queue>
#include<utility>
#include<climits>
using namespace std;
typedef pair<int,int> mp;
int n,m; // n towns and m roads
int S,T; //Source and Terminate
const int maxv=1000+10;
bool vis[maxv];
int dist[maxv]; // dist[i]表示S到i的最短距离
int parent[maxv]; // parent[i]表示S到i的最短路径中i的前一个节点
vector<mp> V[maxv]; //邻接表[i:j1,j2...]和权重w
void dijkstra(int S)
{
//initial
for(int i=0;i<maxv;++i) {dist[i]=INT_MAX;vis[i]=false;}
priority_queue<mp,vector<mp>,greater<mp> > heap;
dist[S]=0; heap.push(mp(0,S));
while( !heap.empty() )
{ //initial
mp now=heap.top(); heap.pop();//pop掉的是当前所有备选顶点中距离S最近的点
int u=now.second;//int uCost=now.first;
if(vis[u]) continue; vis[u]=true;
for(int i=0;i<V[u].size();++i)
{
int v=V[u][i].second;
int edgeCost=V[u][i].first;
if(dist[u]+edgeCost < dist[v]){
dist[v]=dist[u]+edgeCost ;
parent[v]=u;
heap.push(mp(dist[v],v));
}
} //for
}
}
void printPath(int TT)
{
if(parent[TT]==S)
cout<<S<<"->"<<TT;
else{
printPath(parent[TT]);
cout<<"->"<<TT;
}
}
int main()
{
int v1,v2,w,ans;
while(cin>>n>>m)
{
for(int i=0;i<n;++i) V[i].clear();
for(int i=0;i<m;++i)
{
cin>>v1>>v2>>w;
V[v1].push_back(mp(w,v2));
V[v2].push_back(mp(w,v1));
}
cin>>S>>T;
dijkstra(S);
ans=(dist[T]==INT_MAX?-1:dist[T]);
cout<<ans<<endl;
}
}
// HDU 2544 (邻接表+ 优先队列)
#include<iostream>
#include<vector>
#include<queue>
#include<utility>
#include<climits>
using namespace std;
typedef pair<int,int> mp;
struct edge{
int next,cost;
edge(){}
edge(int n,int c):next(n),cost(c){}
};
int n,m; // n towns and m roads
int S,T; //Source and Terminate
const int maxv=1000+1;
int dist[maxv]; // dist[i]表示S到i的最短距离
int previous[maxv]; // prev[i]表示S到i的最短路径中i的前一个节点
vector<edge> V[maxv]; //邻接表[i:j1,j2...]和权重w
int dijkstra(int S,int T)
{
//initial
for(int i=1;i<=n;++i) dist[i]=INT_MAX; dist[S]=0;
priority_queue<mp> heap; heap.push(mp(dist[S],S));
while( !heap.empty() )
{
mp now=heap.top(); heap.pop();//pop掉的是当前所有备选顶点中距离S最近的点
int nowV=now.second;int nowCost=now.first;
//if(nowV==T) return dist[T];
if(nowV!=S && dist[nowV]<= nowCost) continue;//由于顶点的值会更新,旧的会形成冗余
// dist[nowV]是已经确定了的最小距离,nowCost是当前路径下nowV的距离
for(int i=0;i<V[nowV].size();++i)
{
int nextV=V[nowV][i].next;
int edgeCost=V[nowV][i].cost;
if(nowCost+edgeCost < dist[nextV]){
dist[nextV]=nowCost+edgeCost ;
previous[nextV]=nowV;
heap.push(mp(dist[nextV],nextV));
}
} //for
}
return dist[T];
}
int main()
{
int v1,v2,w;
while(cin>>n>>m && n+m)
{
for(int i=1;i<=n;++i) V[i].clear();
for(int i=1;i<=m;++i)
{
cin>>v1>>v2>>w;
V[v1].push_back(edge(v2,w));
V[v2].push_back(edge(v1,w));
}
cout<<dijkstra(1,n)<<endl;
}
}
/// HDU 2066 (邻接矩阵+优先队列)
#include<iostream>
#include<vector>
#include<queue>
#include<utility>
#include<climits>
using namespace std; //why scanf is better than cin???
typedef pair<int,int> mp;
int S,T; //Source and Terminate
const int maxv=1000+50;
bool vis[maxv];
int dist[maxv]; // dist[i]表示S到i的最短距离
int parent[maxv]; // parent[i]表示S到i的最短路径中i的前一个节点
int mat[maxv][maxv]; //邻接矩阵
void dijkstra(int source)
{
initial
for(int i=0;i<maxv;++i) {dist[i]=INT_MAX; vis[i]=false;}
priority_queue<mp,vector<mp>,greater<mp> > heap;
dist[source]=0; heap.push(mp(dist[source],source));
while( !heap.empty() )
{
mp now=heap.top(); heap.pop();//pop掉的是当前所有备选顶点中距离S最近的点
int u=now.second;
if(vis[u]) continue; //可能重复push同一个u
vis[u]=true;
for(int v=1;v<maxv;++v)
if(!vis[v] && mat[u][v]!=INT_MAX && dist[u]+mat[u][v] < dist[v])
{ // relax松弛
dist[v]=dist[u]+mat[u][v] ;
parent[v]=u;
heap.push(mp(dist[v],v));
}
}
}
void printPath(int TT)
{
if(parent[TT]==S)
cout<<S<<"->"<<TT;
else{
printPath(parent[TT]);
cout<<"->"<<TT;
}
}
int main()
{
int v1,v2,w;
int t,s,d,end[maxv]; //t条路径(可重复),d个起点,t个终点
while(cin>>t>>s>>d)
{
初始化邻接矩阵
for(int i=0;i<maxv;++i)
for(int j=i;j<maxv;++j)
mat[i][j]=mat[j][i]=INT_MAX;
输入
for(int i=1;i<=t;++i){
cin>>v1>>v2>>w;
if(mat[v1][v2]>w)//去重
mat[v1][v2]=mat[v2][v1]=w;
}
for(int i=1;i<=s;++i){
cin>>v2;
mat[0][v2]=0; // 多起点,设置统一起点0
}
for(int i=0;i<d;++i)
cin>>end[i]; // 多终点
dijkstra
dijkstra(0); int ans=INT_MAX;
for(int i=0;i<d;++i){
printPath(end[i]);cout<<endl;
if(dist[end[i]]<ans) ans=dist[end[i]];
} //输出最近终点的距离
cout<<ans<<endl;
}
}
/// HDU 2066 (邻接表+优先队列)
#include<iostream>
#include<vector>
#include<queue>
#include<utility>
#include<climits>
using namespace std;
typedef pair<int,int> mp;
int n,m; // n towns and m roads
int S,T; //Source and Terminate
const int maxv=1000+10;
bool vis[maxv];
int dist[maxv]; // dist[i]表示S到i的最短距离
int parent[maxv]; // parent[i]表示S到i的最短路径中i的前一个节点
vector<mp> V[maxv]; //邻接表[i:j1,j2...]和权重w
void dijkstra(int S)
{
//initial
for(int i=0;i<maxv;++i) {dist[i]=INT_MAX;vis[i]=false;}
priority_queue<mp,vector<mp>,greater<mp> > heap;
dist[S]=0; heap.push(mp(0,S));
while( !heap.empty() )
{ //initial
mp now=heap.top(); heap.pop();//pop掉的是当前所有备选顶点中距离S最近的点
int u=now.second;
if(vis[u]) continue; vis[u]=true;
//if(dist[u]< uCost) continue;//由于顶点的值会更新,旧的会形成冗余
// dist[u]是已经确定了的最小距离,uCost是当前路径下u的距离
for(int i=0;i<V[u].size();++i)
{
int v=V[u][i].second;
int edgeCost=V[u][i].first;
if(dist[u]+edgeCost < dist[v]){
dist[v]=dist[u]+edgeCost ;
parent[v]=u;
heap.push(mp(dist[v],v));
}
} //for
}
}
void printPath(int TT)
{
if(parent[TT]==S)
cout<<S<<"->"<<TT;
else{
printPath(parent[TT]);
cout<<"->"<<TT;
}
}
int main()
{
int v1,v2,w;
int t,s,d,end[maxv]; //t条路径(可重复),d个起点,t个终点
while(cin>>t>>s>>d)
{
for(int i=0;i<maxv;++i) V[i].clear();
//输入
for(int i=1;i<=t;++i){
cin>>v1>>v2>>w;
V[v1].push_back(mp(w,v2));
V[v2].push_back(mp(w,v1));
}
for(int i=1;i<=s;++i){
cin>>v2;
V[0].push_back(mp(0,v2)); // 多起点,设置统一起点0
}
for(int i=0;i<d;++i)
cin>>end[i]; // 多终点
dijkstra(0); int ans=INT_MAX;
for(int i=0;i<d;++i){
//printPath(end[i]);cout<<endl;
if(dist[end[i]]<ans) ans=dist[end[i]];
} //输出最近终点的距离
cout<<ans<<endl;
}
}
/// HDU 2112 (邻接矩阵+优先队列)
#include<iostream>
#include<string>
#include<map>
#include<queue>
#include <functional>
#include<climits>
#include<utility>
using namespace std;
typedef pair<int,int> pii;
const int maxv=150+10;
int n,t;
string start,finish,s,e;
map<string,int> mapp;
bool vis[maxv];
int dist[maxv];
//int parent[maxv];
int mat[maxv][maxv];
void dijkstra(int source)
{ // initial
for(int i=0;i<maxv;++i){dist[i]=INT_MAX; vis[i]=false;}
priority_queue<pii,vector<pii>,greater<pii> > heap;
dist[source]=0;heap.push(pii(dist[source],source));
while( !heap.empty() )
{
int u=heap.top().second; heap.pop();
if(vis[u]) continue;
vis[u]=true;
for(int v=0;v<maxv;++v)
if(!vis[v] && mat[u][v]!=INT_MAX && dist[u]+mat[u][v] < dist[v])
{
dist[v]=dist[u]+mat[u][v];
//parent[v]=u;
heap.push(pii(dist[v],v));
}
}
}
int main()
{
while(cin>>n && n+1)
{
cin>>start>>finish;
mapp.clear();
for(int i=0;i<maxv;++i)for(int j=i+1;j<maxv;++j) mat[j][i]=mat[i][j]=INT_MAX;
int k=0; mapp[start]=k++; mapp[finish]=k++;
for(int i=0;i<n;++i){
cin>>s>>e>>t;
if(!mapp.count(s)) mapp[s]=k++;
if(!mapp.count(e)) mapp[e]=k++;
if(t < mat[mapp[s]][mapp[e]])
mat[mapp[e]][mapp[s]]=mat[mapp[s]][mapp[e]]=t;
}
//if(start==finish){cout<<0<<endl;continue;}
//if(n==0){cout<<-1<<endl;continue;}
dijkstra(mapp[start]);
cout<<(dist[mapp[finish]]==INT_MAX?-1:dist[mapp[finish]])<<endl;
}
return 0;
}
写在最后:
HDU 2680 Choose the best route
HDU 1385 Minimum Transport Cost