其实两道题一样的,但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;
}