2016-5-9 回顾: dijkstra = dp+贪心
这个算法实际上不就是,先找一个源点,然后把其他所有点的距离记录下来,遍历一遍所有的边,每一条边我们可以选择更新某一个点(端点)到源点的距离,再拿这个点的的边去松弛别的点(Ps:我也不知道自己是不是在乱J8想,个人感觉这个和dp里面的 更新操作 有一点相似之处,和贪心也有关系,其实都运用到了这几种想法)
先介绍一下刘汝佳书上的算法:
不要用来当模板,应该有很多数据结构在书上,并没有写下来,只是汲取一下其中思想
void dijkstra(int s){
priority_queue<HeapNode> Q; //优先队列,距源点小的点放前面
for(int i=0;i<n;i++) d[i]=inf;
d[s]=0;
memset(done,0,sizeof(done)); //如果对这个点访问过,done设为1
Q.push((HeadNode){0,s});
while(!Q.empty()){
HeadNode x=Q.top(); Q.pop();
int u=x.u; //u是点的编号
if(done[u]) continue;
done[u]=true;
for(int i=0;i<G[u].size();i++){
Edge& e=edges[G[u][i]]; //G[u] 表示从u出发的所有边 ,G[u][i] 表示从u出发第i短 //的边,前面有放入的规则
if(d[e.to]>d[u]+e.dist){
d[e.to]=d[u]+e.dist;
p[e.to]=G[u][i]; //p[e.to] 代表 e.to的编号
}
}
}
}
这个算法的时间复杂度是mlogn ,m代表边数。
这个算法的核心就是优先队列,把d小的点放到前面,做过的点不再进行操作。每次提取的点都是离源点最近的点,以此可以保证d[i]都是最短路径;
poj–3268
题意:http://vj.acmclub.cn/problem/viewProblem.action?id=47402
有N 头牛 在N个农场 将要去X农场举办party, 有M 条路连接这N个农场(或者
N,M,X;
然后M行 每行:from to 和 time;
省略头文件:
using namespace std;
#define MAX_V 8000
#define INF 0x7fffffff //INT_MAX
#define inf 0x3f3f3f3f
// 从顶点from指向顶点to的权值为cost的边
struct edge
{
int to, cost;
edge(){}
edge(int to, int cost) : to(to), cost(cost){}
};
// first 最短路径,second顶点编号
typedef pair<int, int> P;
int flag[MAX_V];
vector<edge> G[MAX_V]; // 图
void intG(){ //初始化图G 很多题目是需要你初始化的图的。
for(int i=1;i<=100;i++)
for(int j=0;j<G[i].size();j++)
G[i][j].cost=inf;
}
// 最短距离
int d[MAX_V][MAX_V]; //这里有个不同点,用d[i][j]表示i,j之间的距离
int V, E; // V是顶点数,E是边数
// 求解从顶点s出发到所有点的最短距离
void dijkstra(int s)
{
mem(flag);
priority_queue<P, vector<P>, greater<P> > que;
memset(d[s], inf, sizeof(d[s]));
d[s][s] = 0; //到本身为0;
que.push(P(0, s));
while (!que.empty())
{
P p = que.top(); que.pop();
int v = p.second;
if (flag[v]) continue; //做过就跳过
flag[v]=1;
for (int i = 0; i < G[v].size(); ++i)
{
edge e = G[v][i];
if (d[s][e.to] > d[s][v] + e.cost)
{
d[s][e.to] = d[s][v] + e.cost;
que.push(P(d[s][e.to], e.to));
}
}
}
}
///SubMain//
int main(int argc, char *argv[])
{
freopen("1.txt", "r", stdin);
int t;
int N,M,X;
while (~scanf("%d %d %d", &N,&M,&X)){
intG();
for(int i=0;i<M;i++){
int a,b,t;
scanf("%d %d %d",&a,&b,&t);
G[a].push_back(edge(b,t)); //存储数据
// G[b].push_back(edge(a,t)); 如果是无向图,记得加这个
}
for(int i=1;i<=N;i++)
dijkstra(i);
int ans=-1;
for(int i=1;i<=N;i++)
ans=max(ans,d[i][X]+d[X][i]);
printf("%d\n",ans);
}
return 0;
}