HDU2066——Dijkstra、Bellman-Ford

传送门

我好菜,题目看着很简单,实际确实很简单,但是还是wa了很多遍。先是白痴地试了一下Floyd,不出意外地超时了。然后直接上手Dijkstra,结果wa了,我,,,确实菜。然后就写了一边Bellman-Ford,ac了,回头的就发现了Dijkstra的问题出在对dis[i]的初始化。

目录

Floyd算法,超时。

Dijkstra,WA。

Dijkstra,AC。

Bellman-Ford,AC。


Floyd算法,超时。

#include<iostream>
#include<algorithm>
using namespace std;
const int inf =  0x3f3f3f3f;
const int num = 1010;

int t, s, d, maxv;
int dis[num][num];
void floyd(){
    for(int k=0; k<maxv; k++)
        for(int i=0; i<maxv; i++)
            for(int j=0; j<maxv; j++)
                if(dis[i][k]<inf && dis[k][j]<inf)
                    if(dis[i][j] > dis[i][k]+dis[k][j])
                        dis[i][j] = dis[i][k]+dis[k][j];
}

int main(){
    while(~scanf("%d%d%d", &t, &s, &d)){
        maxv = 0;
        for(int i=0; i<num; i++){
            for(int j=0; j<num; j++)
                dis[i][j] = inf;
            dis[i][i] = 0;
        }
        
        while(t--){
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            if(a>maxv)    maxv = a;
            if(b>maxv)    maxv = b;
            int x = min(dis[a][b], c);
            dis[a][b] = dis[b][a] = x;
        }
        while(s--){
            int a;
            scanf("%d", &a);
            dis[0][a] = 0;
        }
        floyd();
        
        int mint = inf;
        while(d--){
            int v;
            scanf("%d", &v);
            if(dis[0][v] < mint)    mint = dis[0][v];
        }
        printf("%d\n", mint);
    }
    return 0;
}

Dijkstra,WA。

按习惯,把dis[i]的初始化写在了函数里。

#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int inf =  0x3f3f3f3f;
const int num = 1010;

int t, s, d;
int dis[num];
int pre[num];
int done[num];
struct edge{
    int from, to, w;
    edge(int u, int v, int d){from=u;to=v;w=d;}
};
vector<edge>e[num];

struct node{
    int id, dist;
    node(int u, int d){id=u;dist=d;}
    bool operator <(const node &a)const 
    {    return dist > a.dist;}
};

void dijkstra(){
    for(int i=1; i<num; i++){
        dis[i] = inf;
        pre[i] = done[i] = 0;
    }
    priority_queue<node>q;
    q.push(node(0, 0));
    
    while(!q.empty()){
        node u = q.top();
        q.pop();
        
        if(done[u.id])    continue;
        done[u.id] = 1;
        
        for(int i=0; i<e[u.id].size(); i++){
            edge y = e[u.id][i];
            if(done[y.to])    continue;
            if(dis[y.to] > u.dist + y.w){
                dis[y.to] = u.dist + y.w;
                q.push(node(y.to, dis[y.to]));
                pre[y.to] = u.id;
            }
        }
    }
}

int main(){
    while(~scanf("%d%d%d", &t, &s, &d)){
        for(int i=0; i<num; i++)    e[i].clear();
        
        while(t--){
            int a, b, c;
            scanf("%d%d%d", &a, &b, &c);
            e[a].push_back(edge(a, b, c));
            e[b].push_back(edge(b, a, c));
        }
        while(s--){
            int a;
            scanf("%d", &a);
            e[0].push_back(edge(0, a, 0));
            e[a].push_back(edge(a, 0, 0));
        }
        dijkstra();
        
        int mint = inf;
        while(d--){
            int v;
            scanf("%d", &v);
            if(dis[v] < mint)    mint = dis[v];
        }
        printf("%d\n", mint);
    }
    return 0;
}

Dijkstra,AC。

写完Bellman-Ford的代码之后,我把对dis[i]的初始化写道了主函数下。这题特殊就特殊在有s个城市是和家乡相邻的,而这个相邻的距离直接为0.(呃啊,我有点解释不清,但把dis[i]的初始化改变位置以后确实ac了)

#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int inf =  0x3f3f3f3f;
const int num = 1010;

int t, s, d;
int dis[num];
int done[num];
struct edge{
	int from, to, w;
	edge(int u, int v, int d){from=u;to=v;w=d;}
};
vector<edge>e[num];

struct node{
	int id, dist;
	node(int u, int d){id=u;dist=d;}
	bool operator <(const node &a)const 
	{	return dist > a.dist;}
};

void dijkstra(){
	priority_queue<node>q;
	q.push(node(0, 0));
	
	while(!q.empty()){
		node u = q.top();
		q.pop();
		
		if(done[u.id])	continue;
		done[u.id] = 1;
		
		for(int i=0; i<e[u.id].size(); i++){
			edge y = e[u.id][i];
			if(done[y.to])	continue;
			if(dis[y.to] > u.dist + y.w){
				dis[y.to] = u.dist + y.w;
				q.push(node(y.to, dis[y.to]));
			}
		}
	}
}

int main(){
	while(~scanf("%d%d%d", &t, &s, &d)){
		for(int i=0; i<num; i++){
			e[i].clear();
			dis[i] = inf;
			done[i] = 0;
		}	
		dis[0] = 0;
		
		while(t--){
			int a, b, c;
			scanf("%d%d%d", &a, &b, &c);
			e[a].push_back(edge(a, b, c));
			e[b].push_back(edge(b, a, c));
		}
		while(s--){
            int a;
            scanf("%d", &a);
            e[0].push_back(edge(0, a, 0));
            e[a].push_back(edge(a, 0, 0));
        }
		dijkstra();
		
		int mint = inf;
		while(d--){
			int v;
			scanf("%d", &v);
			if(dis[v] < mint)	mint = dis[v];
		}
		printf("%d\n", mint);
	}
	return 0;
}

Bellman-Ford,AC。

#include<iostream>
#include<algorithm>
#include<queue>
#include<vector>
using namespace std;
const int num = 1001;
const int inf = 0x3f3f3f3f;
 
int t, s, d;
int dis[num];//到原点距离 
int pre[num];//记录前驱节点 
struct edge{
	int u, v, w;
	edge(int a, int b, int c){u=a;v=b;w=c;}
};
vector<edge>e;
 
void print_path(int u, int v){//输出路径 
	if(u==v)	printf("%d", u);
	print_path(u, pre[v]);
	printf("->%d", v);
}
 
void bellman(){
	int k=0, flag=1;
	while(flag){
		k++;
		flag = 0;
		for(int i=0; i<2*t; i++){
			if(dis[e[i].u] > dis[e[i].v] + e[i].w){
				dis[e[i].u] = dis[e[i].v] + e[i].w;
				flag = 1;
				pre[e[i].u] = e[i].v;
			}
		}
	} 
}
 
int main(){
	while(~scanf("%d%d%d", &t, &s, &d)){
        e.clear();
		for(int i=0; i<num; i++)
			dis[i] = inf;
		dis[0] = 0;
		
		for(int i=0; i<t; i++){
			int a, b, c;
			scanf("%d%d%d", &a, &b, &c);
			e.push_back(edge(a, b, c));
			e.push_back(edge(b, a, c));
		}
		while(s--){
			int a;
			scanf("%d", &a);
			dis[a] = 0;
		}
		bellman();
		
		int mint = inf;
		while(d--){
			int a;
			scanf("%d", &a);
			if(mint>dis[a])	mint = dis[a];
		}
		printf("%d\n", mint);
	}
	return 0;
}

 

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值