hdu 2833 dp+floyd
题目意思很简单,就是让你求两天最短路中共同的公共点的最大个数
可以这样理解:
- 我们假设存在2组数据 v0,u0,v1,u1;
- 用path[i][j] 代表 从点i到点j最短路上最多有多少个点!
- 那么 edge[v0][i]+edge[i][j]+edge[j][u0]=edge[v0][u0] 不就表示i到j的最短路为 v0到u0最短路的子路嘛;
- 我们只需更新edge[i][j]中的最大值即可
代码如下。。。。
View Code
1 #include<iostream> 2 const int N=444; 3 const int inf=10000000; 4 using namespace std; 5 6 int edge[N][N]; 7 int path[N][N];//用path[i]][j]来表示i->j的路径上最多有多少个点 8 int n,m; 9 10 void floyd(){ 11 for(int k=1;k<=n;k++){ 12 for(int i=1;i<=n;i++){ 13 if(i==k||edge[i][k]==inf)continue; 14 for(int j=1;j<=n;j++){ 15 if(i==k||j==k||edge[k][j]==inf)continue; 16 if(edge[i][k]+edge[k][j]<edge[i][j]){ 17 edge[i][j]=edge[i][k]+edge[k][j]; 18 path[i][j]=path[i][k]+path[k][j]-1; 19 }else if(edge[i][k]+edge[k][j]==edge[i][j]&&path[i][j]<path[i][k]+path[k][j]){ //此时i,j,k为最短路径上的点 20 path[i][j]=path[i][k]+path[k][j]-1; 21 } 22 } 23 } 24 } 25 } 26 27 int solve(int v0,int u0,int v1,int u1){ 28 int ans=0; 29 if(edge[v0][u0]>=inf||edge[v1][u1]>=inf) 30 return 0; 31 for(int i=1;i<=n;i++){ 32 for(int j=1;j<=n;j++){ 33 if(edge[v0][i]+edge[i][j]+edge[j][u0]==edge[v0][u0]&& 34 edge[v1][i]+edge[i][j]+edge[j][u1]==edge[v1][u1]){ 35 ans=ans>path[i][j]?ans:path[i][j]; 36 } 37 } 38 } 39 return ans; 40 } 41 42 43 int main(){ 44 while(scanf("%d%d",&n,&m)!=EOF){ 45 if(n==0&&m==0)break; 46 for(int i=1;i<=n;i++){ 47 edge[i][i]=0,path[i][i]=1; 48 for(int j=i+1;j<=n;j++){ 49 edge[i][j]=edge[j][i]=inf; 50 path[i][j]=path[j][i]=2; 51 } 52 } 53 int x,y,s; 54 for(int i=1;i<=m;i++){ 55 scanf("%d%d%d",&x,&y,&s); 56 if(edge[x][y]>s){ 57 edge[x][y]=edge[y][x]=s; 58 } 59 } 60 floyd(); 61 int v0,v1,u0,u1; 62 scanf("%d%d%d%d",&v0,&u0,&v1,&u1); 63 int ans=solve(v0,u0,v1,u1); 64 printf("%d\n",ans); 65 } 66 return 0; 67 }
后来在网上看了,也可用记忆化搜索。。。