暑假集训图论周,唉~被虐,不够努力。周末总结一下吧。
本博客参考网上各种资源。如有雷同,不甚荣幸。
Dijkstra:
非常经典的算法。应用贪心的思想,选择距离短的,扩充源集合。
一个顶点属于集合S当且仅当从源到该顶点的最短路径长度已知。
首先有个集合S已知了其内部的最短路,现在要从图中加入一个点到集合S,使集合S里的最短路仍让正确,这时要在图中找一个里S集合
最近的点,加入集合S然后以该点为起点更新dis数组。
int a[MAXN][MAXN];
int d[MAXN];
int N;
int Dijkstra (int s,int e){
int v[MAXN]; //标记已经找到的S数组。
memser(v,0,szieof(v));
fill(d,d+n+1,INF);
d[s]=0;
while (1){
int k=-1;
for (int i=1;i<=n;i++){ //找出其他的点到S数组最近的点
if (v[i]==0&&(k==-1||d[i]<d[v])){
k=1;
}
}
if (k==-1){ //没找到表示最短路寻找完毕。
break;
}
v[k]=1;
for (int i=1;i<=n;i++){ //更新dis数组,
d[i]=min(d[i],d[k]+a[k][i]);
}
}
return d[t]==INF?-1:d[t];
}
当然,Dijkstra还可以用优先队列进行优化,降低时间复杂度。内容大多一样。
int m,n;
int d[MAXN];
int r[MAXN];
typedef pair<int,int >P;
struct Edge{
int v,w;
Edge(int v, int w){
this -> v = v;
this -> w = w;
}
};
vector <Edge> G[MAXN];
priority_queue<P,vector<P>,greater<P> >q;
void dij(int s){
while (!q.empty()) q.pop();
for (int i=1;i<=n;i++){
d[i]=INF;
}
d[s]=0;
q.push(P(0,1));
while (!q.empty()){
P g=q.top();q.pop(); //优先队列,优化找最近的点的时间。
int k=g.second;
for (int i=0;i<G[k].size();i++){//当然邻接表也可以减少跟新次数
Edge p=G[k][i];
if (d[p.v]>d[k]+p.w+r[p.v]){
d[p.v]=d[k]+p.w+r[p.v];
q.push(P(d[p.v],p.v));
}
}
}
}
poj_3628_Silver Cow Party 简单的最短路。每个农场都奶牛们要到X农场里参加聚会,N个农场间有M挑单向路,求出奶牛往返要的最大时间。
两次Dijkstra,第二次要把邻接矩阵转置,
#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
using namespace std;
#define INF 100000000
#define MAXN 1005
int n,m,x;
int a[MAXN][MAXN];
int b[MAXN][MAXN];
int d0[MAXN];
int d1[MAXN];
void dijkstra (int *d,int x,int a[][MAXN]){
int v[MAXN];
for (int i=0;i<MAXN;i++){
d[i]=INF;
v[i]=0;
}
d[x]=0;
while (1){
int k=-1;
for (int i=1;i<=n;i++){
if (v[i]==0&&(k==-1||d[i]<d[k]))
k=i;
}
if (k==-1){
break;
}
v[k]=1;
for (int i=1;i<=n;i++){
d[i]=min(d[i],d[k]+a[k][i]);
}
}
}
void transpose (int a[][MAXN],int b[][MAXN]){
for (int i=1;i<=n;i++){
for (int j=1;j<=n;j++){
b[i][j]=a[j][i];
}
}
}
int main(){
cin>>n>>m>>x;
int u,v,w;
for (int i=0;i<MAXN;i++){
for (int j=0;j<MAXN;j++){
a[i][j]=INF;
}
}
for (int i=1;i<=m;i++){
cin>>u>>v>>w;
a[u][v]=min(a[u][v],w);
}
dijkstra(d0,x,a);
transpose(a,b); //转置,
dijkastra(d1,x,b);
int maxnum=-1;
for (int i=1;i<=n;i++){
maxnum=max(maxnum,d0[i]+d1[i]);
}
cout<<maxnum<<endl;
return 0;
}