hdu 1599 find the mincost route
http://acm.hdu.edu.cn/showproblem.php?pid=1599
【题意】:在一个无向图中找一个 至少有三个不同点的环 而且花费最少
**********************************************************
之前学floyd的时候并没有很认真的去理解那个代码这次写的时候 随手就写出了
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
for(u=1;u<=n;u++)
if(d[i][j]>d[i][u]+d[u][j])
d[i][j]>d[i][u]+d[u][j];
这样的代码 但是后来仔细想想 这样子不行 要求i到j的最短路的时候 先赋初值 他们有边的话就赋为边值没有的话就赋为最大值 然后就是dp 的过程了。
一次一次的用 点k( k从1---->n) 去更新的d[i][j]的值
if(d[i][j]>d[i][k]+d[k][j])
d[i][j]=d[i][k]+d[k][j];//i到j 要经过k点
更新完后的意思就是 点i到点j 经过的点的编号不超过k的最短路径。(不可能经过>k 的点)
如果像之前那样写的话 就太早的 d[i][j]的值确定下来了 (k变化一轮就直接定下来了)
更小的d[i][k]和 d[k][j] 真正算出来了之后 d[i][j]就改变不了了 所以这样是错误的
代码如下:
for(u=1;u<=n;u++)
for(i=1;i<=n;i++)
for(j=1;j<=n;j++)
if(d[i][j]>d[i][u]+d[u][j])
d[i][j]>d[i][u]+d[u][j];
【注意 】:有重边
/*
*/
#include<iostream> #include<stdio.h> #include<string.h> #define INF 100000000 using namespace std; int d[102][102],n,count[102][102],w[102][102]; //i到j 的最短路 int floyd() { int ans=INF,i,j,u; for(u=1;u<=n;u++) { for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(i!=j&&j!=u&&u!=i&&d[i][j]<INF&&w[i][u]<INF&&w[u][j]<INF&&ans>d[i][j]+w[i][u]+w[u][j]) ans=d[i][j]+w[i][u]+w[u][j];
//这里 (i!=j&&j!=u&&u!=i 是为了 保证i-->j的路经过的点不同 注意 这两个for 要写在下面两个for的前面 因为下面两个for求的是中间的点不大于k的最短路径(就称为d[i][j](k)吧)
//在这里只算出了(d[i][j](k-1) 路径里只包含 <k 的一些点) 这样 路径i---->j 再加上边i,k 和边k,j 就 构成了一个环了
for(i=1;i<=n;i++) for(j=1;j<=n;j++) if(d[i][j]>d[i][u]+d[u][j]) d[i][j]=d[i][u]+d[u][j]; } return ans; } int main() { int i,j,m,t,k,a,b,c; while(~scanf("%d%d",&n,&m)) { for(i=1;i<=n;i++) for(j=1;j<=n;j++) { if(i==j) w[i][j]=d[i][j]=0; else w[i][j]=d[i][j]=INF; } for(i=0;i<m;i++) { scanf("%d%d%d",&a,&b,&c); if(c>d[a][b]) continue; d[a][b]=d[b][a]=w[a][b]=w[b][a]=c; } int ans=floyd(); if(ans==INF) printf("It's impossible.\n"); else printf("%d\n",ans); } return 0; }