HDU 1142 A Walk Through the Forest
题意 :
英语不好要遭殃。。。
给你一个图,找最短路。但是有个非一般的的条件:如果a,b之间有路,且你选择要走这条路,那么必须保证a到终点的所有路都小于b到终点的一条路。问满足这样的路径条数 有多少。。。就这个条件,看懂的时候估计都个把小时了
简化一下 a b之间如果有路 就是 1 -> 2 大于 2 -> i
解题思路:
1.1为起点,2为终点,因为要走ab路时,必须保证那个条件,所以从终点开始使用单源最短路Dijkstra算法,就得到了最短的一条路,作为找路的最低限度。
2.然后深搜每条路,看看满足题意的路径有多少条。当然,这个需要从起点开始搜,因为dis[i]数组中保存的都是该点到终点的最短距离。
3.这样搜索之后,dp[1]就是从起点到终点所有满足题意的路径的条数。
#include<bits/stdc++.h> using namespace std; const int maxn = 1010; const int INF = 0x3f3f3f3f; int n,m; bool vis[maxn]; int dp[maxn];//记录方案数 int mp[maxn][maxn]; int d[maxn]; void init() { memset(vis,0,sizeof(vis)); memset(dp,-1,sizeof(dp)); for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) mp[i][j] = INF; } void dijkstral(int st) { for(int i=1;i<=n;i++) d[i] = mp[st][i]; d[st] = 0,vis[st]=1; for(int i=1;i<=n;i++) { int t=INF,k=-1; for(int j=1;j<=n;j++) { if(!vis[j] && d[j]< t) { t = d[j]; k = j; } } if(t == INF) break; vis[k] = 1; for(int j=1;j<=n;j++) { if(!vis[j] && d[j] > d[k]+mp[k][j]) d[j] = d[k] + mp[k][j]; } } } int dfs(int st) { int sum =0; if(dp[st] != -1) return dp[st]; if(st == 2) return 1; for(int i=1;i<=n;i++) { if(mp[st][i] != INF && d[st] > d[i]) sum += dfs(i); } return dp[st] = sum; } int main() { while (~scanf("%d",&n) && n) { scanf("%d",&m); init(); for(int i=1;i<=m;i++) { int x,y,v; scanf("%d %d %d",&x,&y,&v); mp[x][y] = mp[y][x] = v; } dijkstral(2); //for(int i=1;i<=n;i++) //printf("%d ",d[i]); //cout<<endl; printf("%d\n",dfs(1)); } }