HDU 1385 UVA 523 (Bellman-Ford+Floyd)

其实两道题一样的,但uva的输入以及输出格式太考验人。
把hdu这道做出来后,光弄这些输入输出格式弄了两个小时。。。。。。。
不过收获蛮大的。还是自己的基础功不扎实。
总结下来又以下几点:
1.sscanf用的不熟悉。(sprintf)
2.gets用的不好。
先说HDU上的。
Bellman-Ford
其实Bellman-Ford做这个题的解析刚开始看的我挺懵的,做了我一上午才慢慢搞懂,我可真垃圾呀。一开始死活看不懂,一直不明白那块为啥是Bellman-Ford,后来又回归定义,终于想通了。
用Bellman-Ford算法解这道题关键在与这段代码:

for(int l=0;l<n-1;l++){
       for(int i=1;i<=n;i++){
             for(int k=1;k<=n;k++){
                if(i==k||cost[i][k]<0){
                    continue;
                }
                for(int j=1;j<=n;j++){
                    if(route[i][j].cost>cost[i][k]+route[k][j].cost+cost[k][k]||(route[i][j].cost==cost[i][k]+route[k][j].cost+cost[k][k]&&route[i][j].nexthop>k)){
                        //路径从小到大。 
                        route[i][j].cost=cost[i][k]+route[k][j].cost+cost[k][k];
                        route[i][j].nexthop=k;
                    }
                }
            }
        }
    }

第一个for循环不言而喻,他就是循环n-1次,跟原始的Bellman-Ford是一个道理,
第二个for循环就是表示第i个节点,第三个for循环是以k为中间节点进行松弛操作,第四个for循环是第j个节点。
所以就是求i–>j的最短路径,再加上节点上的花费。
为什么中间是用cost[i][k]做计算呢,最重要的是一个原因,因为要输出路径。
其实应用Bellman-Ford算法的思想,本身很容易将此处写成route[i][k].cost,其实这样写最后算的最短路径没问题,不信你可以拿测试样例试试,但是路径就会发生问题,
cost[i][k]保证了路径的准确性,你可以由后往前推想,k是中间节点,cost[i][k]i–>j中间没有进行过松弛,只是对后面进行了松弛,所以第一步先走到k节点,之后的变化跟前面一样,所以保证了路径的正确性,
就比如:i–>k–>s–>j
要是用cost[i][k]的话肯定不会出错,先得出s,再得出k,
然而用route[i][k].cost的话可能会导致i直接就跑到s,而把k给省略了。
付完整代码:

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<cmath>
#include<cstdlib>
#include<list>
#include<queue>
#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define MAXN 0x3fffffff
#define PI acos(-1.0)
#define E exp(1.0)
using namespace std;

//#define debug

struct node{
    int cost;
    int nexthop;
};

node route[300][300];

int cost[300][300];

int n;

bool getmap(){
    scanf("%d",&n);
    if(n==0) return 0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            scanf("%d",&cost[i][j]);
        }
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&cost[i][i]);
    }
    return 1;
}

void init_map(){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i==j){
                route[i][j].cost=0;
                route[i][j].nexthop=j;
                continue;
            }
            if(cost[i][j]<0){
                route[i][j].cost=MAXN;
                route[i][j].nexthop=-1;
            }else{
                route[i][j].cost=cost[i][j];
                route[i][j].nexthop=j;
            }
        }
    }
    for(int l=0;l<n-1;l++){
       for(int i=1;i<=n;i++){
             for(int k=1;k<=n;k++){
                if(i==k||cost[i][k]<0){
                    continue;
                }
                for(int j=1;j<=n;j++){
                    if(route[i][j].cost>cost[i][k]+route[k][j].cost+cost[k][k]||(route[i][j].cost==cost[i][k]+route[k][j].cost+cost[k][k]&&route[i][j].nexthop>k)){
                        //路径从小到大。 
                        route[i][j].cost=cost[i][k]+route[k][j].cost+cost[k][k];
                        route[i][j].nexthop=k;
                    }
                }
            }
        }
    }
}

void solve(){
    int from,to,f;
    while(scanf("%d%d",&from,&to)==2&&from>0){
        printf("From %d to %d :\n",from,to);
        printf("Path: %d",from);
        if(from!=to){
            for(f=route[from][to].nexthop;f!=to;f=route[f][to].nexthop){
                printf("-->%d",f);
            }
            printf("-->%d",to);
        }
        printf("\n");
        printf("Total cost : %d\n\n",route[from][to].cost);
    }
}

int main()
{
    #ifdef debug
    freopen("in.txt","r",stdin);
    freopen("out2.txt","w",stdout);
    #endif // debug

    while(getmap()){
        init_map();
        solve();
    }
    return 0;
}

Floyd
其实这个跟上面那个的时间复杂度相差无几,但这个好理解得多。
刚来开始就一直想用Floyd写的,苦于不知道路径怎么输出。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<cmath>
#include<cstdlib>
#include<list>
#include<queue>
#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define MAXN 0x3fffffff
#define PI acos(-1.0)
#define E exp(1.0)
using namespace std;

//#define debug

int cost[300][300];
int pre[300][300];
int tax[300];

int n;

bool getmap(){
    scanf("%d",&n);
    if(n==0) return 0;
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            scanf("%d",&cost[i][j]);
            if(cost[i][j]==-1) cost[i][j]=MAXN;
        }
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&tax[i]);
    }
    return 1;
}

void floyd(){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            pre[i][j]=j;
        }
    }
    for(int k=1;k<=n;k++){
        for(int i=1;i<=n;i++){
            for(int j=1;j<=n;j++){
                if(cost[i][k]>0&&cost[k][j]>0){
                        if(cost[i][j]>cost[i][k]+cost[k][j]+tax[k]){
                        cost[i][j]=cost[i][k]+cost[k][j]+tax[k];
                        pre[i][j]=pre[i][k];
                    }
                    else if(cost[i][j]==cost[i][k]+cost[k][j]+tax[k]){
                        pre[i][j]=min(pre[i][k],pre[i][j]);
                    }
                }
            }
        }
    }
}

void solve(){
    int from,to,f;
    while(scanf("%d%d",&from,&to)==2&&from>0){
        printf("From %d to %d :\n",from,to);
        printf("Path: %d",from);
        if(from!=to){
            for(f=pre[from][to];f!=to;f=pre[f][to]){
                printf("-->%d",f);
            }
            printf("-->%d",to);
        }
        printf("\n");
        printf("Total cost : %d\n\n",cost[from][to]);
    }
}

int main()
{
    #ifdef debug
    freopen("in.txt","r",stdin);
    freopen("out2.txt","w",stdout);
    #endif // debug

    while(getmap()){
        floyd();
        solve();
    }
    return 0;
}

uva就跟hdu思想一摸一样。就是输入输出格式变了

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<string>
#include<map>
#include<vector>
#include<cmath>
#include<cstdlib>
#include<list>
#include<queue>
#define mm(a,b) memset(a,b,sizeof(a))
#define ACCELERATE (ios::sync_with_stdio(false),cin.tie(0))
typedef long long ll;
typedef long double ld;
typedef unsigned long long ull;
#define MAXN 0x3fffffff
#define PI acos(-1.0)
#define E exp(1.0)
using namespace std;

//#define debug

struct node{
    int cost;
    int nexthop;
};

node route[1025][1025];

int cost[1025][1025];
int casei;

int n;
char str[1025];

void  getmap(){
    n=0;
    char ch;
    int ans=0;
    int flag=1;
    while(gets(str)&&!str[0]);
    int len=strlen(str);
    str[len]=' ';
    str[len+1]=0;
    for(int i=0;str[i];i++){
        if(isdigit(str[i]))
            ans=ans*10+str[i]-'0';
        else if(str[i]=='-') flag=-1;
        else {
            cost[1][++n]=ans*flag;
            flag=1;ans=0;
        }
    }
    for(int i=2;i<=n;i++){
        for(int j=1;j<=n;j++){
            scanf("%d",&cost[i][j]);
        }
    }
    for(int i=1;i<=n;i++){
        scanf("%d",&cost[i][i]);
    }
    getchar();
}

void init_map(){
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            if(i==j){
                route[i][j].cost=0;
                route[i][j].nexthop=j;
                continue;
            }
            if(cost[i][j]<0){
                route[i][j].cost=MAXN;
                route[i][j].nexthop=-1;
            }else{
                route[i][j].cost=cost[i][j];
                route[i][j].nexthop=j;
            }
        }
    }
    for(int l=0;l<n-1;l++){
        for(int i=1;i<=n;i++){
            for(int k=1;k<=n;k++){
                if(i==k||cost[i][k]<0){
                    continue;
                }
                for(int j=1;j<=n;j++){
                    if(route[i][j].cost>cost[i][k]+route[k][j].cost+cost[k][k]||(route[i][j].cost==cost[i][k]+route[k][j].cost+cost[k][k]&&route[i][j].nexthop>k)){
                        route[i][j].cost=cost[i][k]+route[k][j].cost+cost[k][k];
                        route[i][j].nexthop=k;
                    }
                }
            }
        }
    }
}


void solve(){
    int from,to,f;

    while(gets(str)&&str[0]){
        sscanf(str,"%d%d",&from,&to);
        if (casei ++) {
                puts("");
            }
        printf("From %d to %d :\n",from,to);
        printf("Path: %d",from);
        if(from!=to){
            for(f=route[from][to].nexthop;f!=to;f=route[f][to].nexthop){
                printf("-->%d",f);
            }
            printf("-->%d",to);
        }
        printf("\n");
        printf("Total cost : %d\n",route[from][to].cost);
    }
}

int main()
{
    #ifdef debug
    freopen("in.txt","r",stdin);
//    freopen("out2.txt","w",stdout);
    #endif // debug
    int m;
    scanf("%d",&m);
    while(m--){
        getmap();
        init_map();
        solve();
    }

    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值