HDU 1142 A Walk Through the Forest (dijkstra算法)

地址:http://acm.hdu.edu.cn/showproblem.php?pid=1142

思路1:

题目大意是给你一个图。起点为1,终点为2

然后点a到点b是合法的判断(Notice 1:)是当b存在一个到终点的距离小于a到终点的最小距离,求从起点到终点的路径数。

Notice 1:不合法并非是断路,合法指回家的时候只按dis[b] < dis[a]的路线走、

dis[]表示到终点2的最短路径, 满足dis[b] < dis[a], 表示这样a->b的是可选择的。 就是说每次回家时选择从距起点(最短距离)近的点 向 距起点(最短距离)远的点走, 求这样的路线条数。

dp[i] = sum{ dp[j] |  i->j邻接 && dp[j] > dp[i]};

//即邻接的两点(i,j)且 i->j 的路线是可行的,到 j 的路径数是其所以前驱点路径数之和

 for (j = 1; j <= n; j++)

{

if (i->j 邻接 且 dis[j] > dis[i])

{

then i->j的路线是可选择的;

dp[i] += dp[j];

}

}

借鉴代码1如下:

  1 #include <iostream>
  2 #include <cstring>
  3 #include <cstdio>
  4 #include <queue>
  5 #include <algorithm>
  6 using namespace std;
  7 #define INF 0x7fffffff  //这个是把inf赋值为一个极大值。你可以这样认为0x7fffffff是十六进制的-1,那么把它减1就相当于正的最大值
  8 #define MAXN 1010
  9 int map[MAXN][MAXN];
 10 int dis[MAXN];
 11 int dp[MAXN];
 12 bool hash[MAXN];
 13 struct Dij
 14 {
 15     int id;
 16     int dis;
 17     bool friend operator < (const Dij a, const Dij b)
 18     {
 19         return a.dis > b.dis;
 20     }
 21 };
 22 Dij now, next;
 23 void Init(int n)
 24 {
 25     for (int i = 0; i <= n; i++)
 26     {
 27         map[i][i] = 0;
 28         for (int j = i + 1; j <= n; j++)
 29         {
 30             map[i][j] = map[j][i] = INF;
 31         }
 32     }
 33 }
 34 void Bfs(int st, int n)
 35 {
 36     memset(hash, false, sizeof(hash));
 37     for (int i = 1; i <= n; i++)
 38     {
 39         dis[i] = INF;
 40     }
 41     priority_queue<Dij> Q;
 42     now.id = st;
 43     now.dis = 0;
 44     dis[st] = 0;
 45     Q.push(now);
 46     
 47     while (!Q.empty())
 48     {
 49         now = Q.top();
 50         Q.pop();
 51         if (hash[now.id])
 52         {
 53             continue;
 54         }
 55         hash[now.id] = true;
 56         
 57         for (int j = 1; j <= n; j++)
 58         {
 59             if (!hash[j] && map[now.id][j] != INF && 
 60             dis[j] > dis[now.id] + map[now.id][j])
 61             {
 62                 dis[j] = dis[now.id] + map[now.id][j];
 63                 next.id = j;
 64                 next.dis = dis[j];
 65                 Q.push(next);
 66             }
 67         }
 68     }
 69 }
 70 int dp_num(int ed, int n)
 71 {
 72     if (dp[ed] != 0)
 73     {//不为0,说明已求得,直接返回。
 74         return dp[ed];
 75     }
 76     for (int j = 1; j <= n; j++)
 77     {
 78         if (j != ed && map[j][ed] != INF)
 79         {
 80             if (dis[j] < dis[ed])
 81             {
 82                 dp[ed] += dp_num(j, n);
 83                 //dis表示到终点2的最短路径,即按题意求dis[b] < dis[a]的路径数目。
 84             }
 85         }
 86     }
 87     return dp[ed];
 88 }
 89 int main()
 90 {
 91     int n, m, i, j;
 92     int a, b, c;
 93     while (scanf("%d", &n) != EOF)
 94     {
 95         if (n == 0)
 96             break;
 97         Init(n);
 98         scanf("%d", &m);
 99         for (i = 0; i < m; i++)
100         {
101             scanf("%d %d %d", &a, &b, &c);
102             if (c < map[a][b])
103             {
104                 map[a][b] = map[b][a] = c;
105             }
106         }
107         Bfs(2, n);
108         memset(dp, 0, sizeof(dp));
109         dp[2] = 1;//只要dis表示到终点2的最短路即可,dfs可以从起点->终点,也可以从终点->起点
110         dp_num(1, n);//dfs求路径数
111         printf("%d/n", dp[1]);
112     }
113     return 0;
114 }

借鉴代码2如下:

 1 #include<stdio.h>
 2 int n,map[1001][1001];
 3 int dist[1001],s[1001],dp[1001];
 4 int dfs(int v)//深搜
 5 {
 6     int i,temp,sum=0;
 7     if(dp[v]!=-1)
 8         return dp[v];
 9     if(v==2)
10         return 1;
11     for(i=1;i<=n;i++)
12     {
13         if(map[v][i]!=2000000&&dist[v]>dist[i])//
14         {
15             temp=dfs(i);
16             sum+=temp;
17         }
18     }
19     dp[v]=sum;
20     return sum;
21 }
22 void dijkstra(int v)//dijkstra求最短路
23 {
24     int i,j,u,min;
25     for(i=1;i<=n;i++)
26         dist[i]=map[v][i];
27     dist[v]=0;
28     s[v]=1;
29     for(i=1;i<n;i++)
30     {
31         min=2000000;
32         for(j=1;j<=n;j++)
33         {
34             if(!s[j]&&dist[j]<min)
35             {
36                 min=dist[j];
37                 u=j;
38             }
39         }
40         s[u]=1;
41         for(j=1;j<=n;j++)
42         {
43             if(!s[j]&&dist[j]>dist[u]+map[u][j])
44             {
45                 dist[j]=dist[u]+map[u][j];
46             }
47         }
48     }
49 }
50 int main()
51 {
52     int i,j,x,m;
53     while(scanf("%d",&n),n)
54     {
55         for(i=1;i<=n;i++)
56         {
57             s[i]=0;
58             dp[i]=-1;
59             for(j=1;j<=n;j++)
60                 map[i][j]=2000000;
61         }
62         scanf("%d",&m);
63         while(m--)
64         {
65             scanf("%d%d%d",&i,&j,&x);
66             map[i][j]=map[j][i]=x;
67         }
68         dijkstra(2);
69         dfs(1);
70         printf("%d/n",dp[1]);
71     }
72     return 0;
73 }

 

思路2:

本题的思想就是dfs+dijkstra。本题的意思是,如果在点B出存在一条路使得从B点出发可以比从A点出发跟快的到达home,所以B到home的最短距离要比A到home得最短距离小,所以本题首先要求出各点到home得距离,然后再用记忆搜索法搜索即可

借鉴代码如下:

  1 #include<stdio.h>
  2  #include<string.h>
  3  #include<queue>
  4   using namespace std;
  5   int dist[1005],dp[1005];
  6  typedef struct t
  7  {
  8      int end,len;
  9      struct t *next;
 10  }T;
 11  struct node
 12  {
 13      int data;
 14      int len;
 15      bool operator <(const node &a)const
 16      {
 17          return a.len<len;
 18      }
 19      T *next;
 20  }s[1005];
 21  void dijkstra(int v0)
 22  {
 23      s[v0].len=0;node cur;
 24      int visit[1005],mark=0;
 25      memset(visit,0,sizeof(visit));
 26      memset(dist,-1,sizeof(dist));
 27      priority_queue<node> qu;
 28      qu.push(s[v0]);
 29      dist[v0]=0;
 30      while(!qu.empty ())
 31      {
 32          cur=qu.top();
 33          while(visit[cur.data])
 34          {
 35              qu.pop();
 36              if(qu.empty ())
 37              {
 38                  mark=1;
 39                  break;
 40              }
 41              cur=qu.top();
 42          }
 43          if(mark)
 44              break;
 45          qu.pop();
 46          visit[cur.data]=1;
 47          T *p=cur.next;
 48          while(p)
 49          {
 50              if(!visit[p->end])
 51              {
 52                  if(dist[p->end]==-1||dist[cur.data]+p->len<dist[p->end] )
 53                      s[p->end].len=dist[p->end]=p->len+dist[cur.data];
 54                  qu.push (s[p->end]);
 55              }
 56              p=p->next;
 57          }
 58      }
 59  }
 60  int dfs(int v0)
 61  {
 62      int temp=0;
 63      if(v0==2)
 64          return 1;
 65      if(dp[v0]!=-1)
 66          return dp[v0];
 67      t *p=s[v0].next;
 68      while(p)
 69      {
 70          if(dist[v0]>dist[p->end])
 71          {
 72              dp[p->end]=dfs(p->end);
 73              temp+=dp[p->end];
 74          }
 75          p=p->next;
 76      }
 77      return temp;
 78  }
 79  int main()
 80  {
 81      int n,i,m,a,b,len;
 82      while(scanf("%d",&n)!=EOF)
 83      {
 84          if(n==0)
 85              break;
 86          scanf("%d",&m);
 87          T *p,*q;
 88          for(i=1;i<=n;i++)
 89          {
 90              s[i].next=NULL;
 91              s[i].data=i;
 92          }
 93          memset(dp,-1,sizeof(dp));
 94          for(i=1;i<=m;i++)
 95          {
 96              scanf("%d%d%d",&a,&b,&len);
 97              p=(T*)malloc(sizeof(T));
 98              p->end=b;
 99              p->len=len;
100              p->next=s[a].next;
101              s[a].next=p;
102              q=(T*)malloc(sizeof(T));
103              q->end=a;
104              q->len=len;
105              q->next=s[b].next;
106              s[b].next=q;
107          }
108          dijkstra(2);
109          printf("%d\n",dfs(1));
110      }
111      return 0;
112  }

 

思路3:


题目大意是给一个图。起点为1,终点为2

然后点a到点b是合法的判断是当b存在一个到终点的距离小于a到终点的最小距离。。。。。求从起点到终点的路径数。。

我的做法是dijk + sort + dp。

先dijk出任何点到2的最小距离。然后按照距离对他们sort 。

dp就是很普通的路径dp:ans[终点] += ans[起点];

借鉴代码如下:

  1 #include<iostream>
  2 #include<algorithm>
  3 #include<queue>
  4 using namespace std;
  5 #define MAXN 1100
  6 #define INF 1000000000
  7 
  8 struct way
  9 {
 10     int s;
 11     int d;//distance
 12     bool operator <(const way k)const
 13     {
 14         return d < k.d;
 15     }
 16 };
 17 
 18 struct point//restore id and d(distance) of each point
 19 {
 20     int d,id;
 21     bool operator<(const point &a) const//used for sort
 22     {
 23         if(d==a.d)
 24             return a.id>id;//从小到大排id
 25         return a.d<d;//从大到小排distance
 26     }
 27 }p[MAXN];
 28 
 29 int n,ans[MAXN];
 30 int map[MAXN][MAXN];
 31 bool flag[MAXN];
 32 
 33 void dijk()//dijk find minimal distance between each point to point 2
 34 {
 35     priority_queue<way>Q;
 36 
 37     way temp,now;
 38     now.s=2;
 39     now.d=0;
 40     Q.push(now);
 41     p[2].d=0;
 42 
 43     while(!Q.empty())
 44     {
 45         now=Q.top();
 46         Q.pop();//use priority queue to ensure pop the point with minimal distance every time
 47         if(flag[now.s])
 48             continue;
 49         flag[now.s]=1;//flag[i]==1 means it is in the end point set
 50         for(int i=1;i<=n;i++)//从终点往回推
 51         {
 52             if(!flag[i]&&map[now.s][i]!=INF&&p[i].d>p[now.s].d+map[now.s][i])
 53             {
 54                 temp.s=i;
 55                 temp.d=p[now.s].d+map[now.s][i];
 56                 p[i].d=temp.d;
 57                 Q.push(temp);
 58             }
 59         }
 60     }
 61 }
 62 
 63 void init(int m)//初始化
 64 {
 65     int i,j;
 66     int a,b,c;
 67     for(i=1;i<=n;i++)
 68     {
 69         p[i].id=i;
 70         flag[i]=0;
 71         p[i].d=INF;
 72         ans[i]=0;
 73         for(j=1;j<=n;j++)
 74             map[i][j]=INF;
 75     }
 76     while(m--)
 77     {
 78         scanf("%d%d%d",&a,&b,&c);
 79         map[a][b] = c;
 80         map[b][a] = c;
 81     }
 82 }
 83 
 84 void dp()//ans[end point]+=ans[start point]
 85 {
 86     int i,j;
 87     for(i=1;i<=n;i++)//find start point 1
 88         if(p[i].id==1)
 89             break;
 90     ans[1]=1;
 91     for(i;i<n;i++)
 92     {
 93         for(j=i+1;j<=n;j++)//p[j].d must be <= p[i].d after sorting
 94         {
 95             if(map[p[j].id][p[i].id]!=INF&&p[j].d<p[i].d)
 96                 ans[p[j].id]+=ans[p[i].id];
 97         }
 98     }
 99 }
100 
101 int main()
102 {
103     int m;
104     while(scanf("%d",&n)!=EOF&&n!=0)
105     {
106         scanf("%d",&m);
107         init(m);
108         dijk();//find minimal distance between each point to point 2
109         sort(p+1,p+n+1);//sort the distance
110         dp();
111         printf("%d/n",ans[2]);
112     }
113     return 0;
114 }

posted on 2012-08-21 12:28  mycapple  阅读(296)  评论(0编辑  收藏  举报

导航