之前很认真地看了用优先队列来实现Dijkstra这块,借鉴了小白书上的代码模板后,便拿这道题来试试水了。这道题的大意就是问你从地点1到地点2有多少条满足条件的路径(假设该路径经过 1->...-> a -> b ->...-> 2,那么d[b]必须小于d[a],其中d[b],d[a]分别是指 b,a 到地点2的最短距离),所以大体做法就是先求出以2为起点的单源最短路径,然后利用深搜dfs(v)表示 v顶点到2的满足以上条件的路径数,最后答案便是dfs(1),当然要加个记忆化。

  因为我主要是拿来练习Dijkstra,所以深搜这部分可以不用变,先附上用邻接矩阵来实现的最原始的Dijkstra:

 #include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
typedef long long LL;
const int INF= 0x3fffffff;
const int maxN= ; int n, w[maxN+][maxN+]; bool vis[maxN+];
int d[maxN+];
void Dijkstra(int u){
memset(vis,,sizeof(vis));
for(int i=; i<=n; ++i)
d[i]= INF;
d[u]= ;
while(){
int x, m =INF;
for(int y=; y<=n; ++y)
if(!vis[y] && m>d[y]) m= d[x=y];
if(m==INF) break;
vis[x]= ;
for(int y=; y<=n; ++y)
if(w[x][y]!=INF) d[y]= min(d[y],d[x]+w[x][y]);
}
} int dp[maxN+];
int dfs(int v){
if(dp[v]!=-) return dp[v];
if(v==) return ;
dp[v]= ;
for(int i=; i<=n; ++i)
if(w[v][i]!=INF && d[i]<d[v]) dp[v]+= dfs(i);
return dp[v];
} int main(){
int m,i,j,x,y,z;
while(scanf("%d",&n),n){
scanf("%d",&m);
for(i=; i<=maxN; ++i)
for(j=i; j<=maxN; ++j)
w[i][j]= w[j][i]= INF;
while(m--){
scanf("%d%d%d",&x,&y,&z);
w[x][y]= w[y][x]= z;
}
Dijkstra();
memset(dp,-,sizeof(dp));
printf("%d\n",dfs());
}
return ;
}

  然后dfs部分保持不变,Dijkstra改用邻接表+优先队列来实现,小白书上也有比较详细的代码了,可是这道题是无向图,而小白书上的代码仅仅适用于有向图,需要作少许的更改(这一点点更改已经让我痛苦了好久T.T ,我不想再回忆了T.T)。

  在邻接表的读入这部分调试了好久,因为对于题目中的每条边都需要手动把它拆成两条边再存进结点数组和边数组中,刘汝佳的书中读入和邻接表的预处理是合在一起的(后来才发现这对我调试带来了大大的不便),所以在最终的代码里我把它们分开来了,感觉代码清爽多了。

  (因为dfs中需要访问两结点间是否存在边,如果单纯去遍历邻接表的话恐怕会超时,所以终究要用到一个邻接矩阵edge[][],只不过该矩阵用bool 来定义即可,因为只需记录两结点间是否有边(1/0),边权值已存放在了w[]数组中):

 #include<cstdio>
#include<cstring>
#include<map>
#include<queue>
#include<vector>
#include<algorithm>
using namespace std;
const int INF= 0x3fffffff;
const int maxN= ;
const int maxM= ; int n,m;
bool edge[maxN+][maxN+];
int first[maxN+];
int u[maxM+], v[maxM+], w[maxM+], Next[maxM+]; //边读入邻接表中:
void read_graph()
{
memset(first,-,sizeof(first)); //一开始我是这个读法,把所有的边整体复制到原始边的最后面,思路是没有错,
//但就是因为少了 v[e+m]= u[e]的复制足够让我几乎想破了脑袋也想不出来,
//因为当时是凌晨2点多做的,头脑不清醒以为边的终点 v[e]用不上所以不用复制,
//但Dijkstra中是所有的信息都要用到的,包括 起点,终点,边权值,三者缺一不可!
/* for(int e=0; e<m; ++e)
{
scanf("%d%d%d",u+e,v+e,w+e);
u[e+m]= v[e];
v[e+m]= u[e]; //就是少了这个,结果错成狗!
w[e+m]= w[e];
edge[u[e]][v[e]]= edge[v[e]][u[e]]= true;
}*/ //然后这种读法是每读入一条边,就把它紧凑地复制到下一个位置,注意 e每次循环是加 2的
for(int e=; e<*m; e+=)
{
scanf("%d%d%d",u+e,v+e,w+e);
u[e+]= v[e];
v[e+]= u[e]; //记得也要有这个,不然同样错成狗!
w[e+]= w[e];
edge[u[e]][v[e]]= edge[v[e]][u[e]]= true; /* Next[e]= first[u[e]]; //一边读入一边处理也可以,
first[u[e]]= e; Next[e+1]= first[u[e+1]];
first[u[e+1]]= e+1;*/
} //把邻接表的处理放在后面就更清晰,代码更清爽。
for(int e=; e<*m; ++e)
{
Next[e]= first[u[e]];
first[u[e]]= e;
}
} //优先队列所需的一切数据结构
typedef pair<int,int> pii;
priority_queue<pii, vector<pii>, greater<pii> > q;
bool done[maxN+];
int d[maxN+]; void Dijkstra(int u){
memset(done,,sizeof(done));
for(int i=; i<=n; ++i)
d[i]= INF;
d[u]= ;
q.push(pii(d[u],u));
while(!q.empty()){
int x= q.top().second; q.pop();
if(done[x]) continue;
done[x]= ;
for(int e= first[x]; e!= -; e= Next[e])
if(d[x]!=INF && d[v[e]] > d[x]+w[e]){
d[v[e]]= d[x]+w[e];
q.push(pii(d[v[e]],v[e]));
}
}
} int dp[maxN+];
int dfs(int v){
if(dp[v]!=-) return dp[v];
if(v==) return ;
dp[v]= ;
for(int i=; i<=n; ++i)
if(edge[v][i] && d[i]<d[v]) dp[v]+= dfs(i);
return dp[v];
} int main(){
while(scanf("%d",&n),n){
scanf("%d",&m);
memset(edge,,sizeof(edge));
read_graph();
Dijkstra();
memset(dp,-,sizeof(dp));
printf("%d\n",dfs());
}
return ;
}

hdu 1142 用优先队列实现Dijkstra的更多相关文章

  1. hdu 1142 最短路+记忆化

    最短路+记忆化搜索HDU 1142 A Walk Through the Forest链接:http://acm.hdu.edu.cn/showproblem.php?pid=1142 > 题意 ...

  2. poj 1511 优先队列优化dijkstra *

    题意:两遍最短路 链接:点我 注意结果用long long #include<cstdio> #include<iostream> #include<algorithm& ...

  3. POJ 1511 Invitation Cards (ZOJ 2008) 使用优先队列的dijkstra

    传送门: http://poj.org/problem?id=1511 http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemId=1008 ...

  4. HDU 1535 Invitation Cards(逆向思维+邻接表+优先队列的Dijkstra算法)

    题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=1535 Problem Description In the age of television, n ...

  5. HDU 2544最短路 【dijkstra 链式前向星+优先队列优化】

    最开始学最短路的时候只会用map二维数组存图,那个时候还不知道这就是矩阵存图,也不懂得效率怎么样 经过几个月的历练再回头看最短路的题, 发现图可以用链式前向星来存, 链式前向星的效率是比较高的.对于查 ...

  6. hdu 1142(DFS+dijkstra)

    #include<iostream> #include<cstdio> #include<cmath> #include<map> #include&l ...

  7. HDU 1142 A Walk Through the Forest(dijkstra+记忆化DFS)

    题意: 给你一个图,找最短路.但是有个非一般的的条件:如果a,b之间有路,且你选择要走这条路,那么必须保证a到终点的所有路都小于b到终点的一条路.问满足这样的路径条数 有多少,噶呜~~题意是搜了解题报 ...

  8. HDU 1142 A Walk Through the Forest(Dijkstra+记忆化搜索)

    题意:看样子很多人都把这题目看错了,以为是求最短路的条数.真正的意思是:假设 A和B 是相连的,当前在 A 处, 如果 A 到终点的最短距离大于 B 到终点的最短距离,则可以从 A 通往 B 处,问满 ...

  9. ACM: HDU 1874 畅通工程续-Dijkstra算法

    HDU 1874 畅通工程续 Time Limit:1000MS     Memory Limit:32768KB     64bit IO Format:%I64d & %I64u Desc ...

随机推荐

  1. 局域网 其它主机ping不通win7, 解决

    默认情况下,Windows 7出于安全考虑不允许外部主机对其进行Ping测试. 允许ICMP回显 设置如下: 1. 打开win7防火墙设置界面 2. 左边的菜单中选择 [高级设置] 3. 在弹出的 [ ...

  2. java.lang.VerifyError异常

    以前遇到过java.lang.VerifyError 原因是jar包冲突 tomcat6自带jsp.jar.servlet.jar所以项目中不用引入 tomcat5不带jsp.jar.servlet. ...

  3. SlickGrid example 8:折线图

    根据数据生成折线图,使用相当简单,也很容易.     主要方法: 数据: var vals = [12,32,5,67,5,43,76,32,5]; 生成折线图: $("testid&quo ...

  4. Android GridView 第一个Item 点击没反应

    @Override public View getView(final int position, View convertView, ViewGroup parent) { final ViewHo ...

  5. 【C++】智能指针

    auto_ptr auto_ptr是当前C++标准库中提供的一种智能指针. auto_ptr在构造时获取某个对象的所有去(ownership),在析构时释放该对象.我们可以这样使用auto_ptr来提 ...

  6. pip命令使用国内pypi镜像源加速在线安装

    参考:http://www.cnblogs.com/yudar/p/4444097.html 用easy_install和pip来安装第三方库很方便 它们的原理其实就是从Python的官方源pypi. ...

  7. jquery easyui 弹出消息框

    <html> <head> <!-- 导入easyui插件的js和css样式; --> <link rel="stylesheet" ty ...

  8. 控制窗口不能拖拉出主窗口 Dialog And Window

    /* 控制窗口不能拖拉出主窗口(覆写) */var easyuiPanelOnMove = function(left, top) { if ($(this).panel('options').reS ...

  9. 2016年7月1日 星期五 --出埃及记 Exodus 14:28

    2016年7月1日 星期五 --出埃及记 Exodus 14:28 The water flowed back and covered the chariots and horsemen--the e ...

  10. PowerDesigner连接SqlServer数据库