最短路
Time Limit: 5000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)
Problem Description
在每年的校赛里,所有进入决赛的同学都会获得一件很漂亮的t-shirt。但是每当我们的工作人员把上百件的衣服从商店运回到赛场的时候,却是非常累的!所以现在他们想要寻找最短的从商店到赛场的路线,你可以帮助他们吗?
Input
输入包括多组数据。每组数据第一行是两个整数N、M(N<=100,M<=10000),N表示成都的大街上有几个路口,标号为1的路口是商店所在地,标号为N的路口是赛场所在地,M则表示在成都有几条路。N=M=0表示输入结束。接下来M行,每行包括3个整数A,B,C(1<=A,B<=N,1<=C<=1000),表示在路口A与路口B之间有一条路,我们的工作人员需要C分钟的时间走过这条路。
输入保证至少存在1条商店到赛场的路线。
Output
对于每组输入,输出一行,表示工作人员从商店走到赛场的最短时间
Sample Input
2 1
1 2 3
3 3
1 2 5
2 3 5
3 1 2
0 0
Sample Output
3
2
题目链接:最短路
代码:
//Dijkstra
#include
#include
#include
#include
using namespace std;
const int MAX = 1 << 30;
int n,m,vis[110],dist[110];
struct node //存储边的终点,以及权值
{
int v,w;
node(int vv,int ww) : v(vv),w(ww) {}
node() {}
};
vector G[110];
void make_G()
{
int st,ed,c;
for(int i = 1;i <= n;i++) { //初始化
G[i].clear();
vis[i] = 0;
dist[i] = MAX;
}
for(int i = 0;i < m;i++) {
scanf("%d%d%d",&st,&ed,&c);
G[st].push_back(node (ed,c));
G[ed].push_back(node (st,c));
}
}
void dijkstra()
{
dist[1] = 0;
for(int i = 0;i < n;i++) { //从未选点集中选点,并加入已选点集
int p,mn = MAX;
for(int j = 1;j <= n;j++) { //未选点 中 距离 已选点 最近的点
if(!vis[j] && dist[j] <= mn) {
p = j,mn = dist[j];
}
}
vis[p] = 1; //标记选择
for(int j = 0;j < G[p].size();j++) { //更新选择后的dist数组,也就是源点到其他点的最短距离
if(dist[G[p][j].v ] > dist[p] + G[p][j].w){
dist[G[p][j].v ] = dist[p] + G[p][j].w;
}
}
}
printf("%d\n",dist[n]);
}
int main()
{
while(~scanf("%d%d",&n,&m) && n && m) {
make_G();
dijkstra();
}
return 0;
}#include
#include
#include
#include
using namespace std;
int n,m,vis[110];
struct node
{
int v,w;
node(int vv,int ww) : v(vv),w(ww) {}
node() {}
bool operator < (const node &a) const //运算符重载,保证权值小的边优先级高
{
return w > a.w;
}
};
vector G[110];
void make_G()
{
int st,ed,c;
for(int i = 1;i <= n;i++) {
G[i].clear();
vis[i] = 0;
}
for(int i = 0;i < m;i++) {
scanf("%d%d%d",&st,&ed,&c);
G[st].push_back(node (ed,c));
G[ed].push_back(node (st,c));
}
}
void dijkstra()
{
priority_queue qe;
qe.push(node (1,0));
node p;
while(!qe.empty()) {
p = qe.top();
qe.pop();
if(vis[p.v]) continue; //之前处理过(队列先处理最优的)
vis[p.v] = 1;
if(p.v == n) break;
for(int i = 0;i < G[p.v].size();i++) {
node q = G[p.v][i];
if(!vis[q.v]) { //从已选点开始可更新的边都入队,当然也可以改成判断队列是否已经有这条边
q.w = p.w + q.w;
qe.push(node (q.v,q.w));
}
}
}
printf("%d\n",p.w);
}
int main()
{
while(~scanf("%d%d",&n,&m) && n && m) {
make_G();
dijkstra();
}
return 0;
}//bellman-ford
#include
#include
#include
#include
using namespace std;
const int MAX = 1<<30;
int n,m,vis[110],dist[110];
struct node
{
int u,v,w;
node(int uu,int vv,int ww) : u(uu),v(vv),w(ww) {}
node() {}
};
vector G;
void make_G()
{
int st,ed,c;
G.clear();
for(int i = 1;i <= n;i++) {
vis[i] = 0;
dist[i] = MAX;
}
for(int i = 0;i < m;i++) {
scanf("%d%d%d",&st,&ed,&c);
G.push_back(node (st,ed,c));
G.push_back(node (ed,st,c));
}
}
void bellman_ford()
{
dist[1] = 0;
for(int j = 1;j < n;j++) { //n-1次松弛
for(int i = 0;i < G.size();i++) { //对每条边进行处理
int u,v;
u = G[i].u,v = G[i].v;
if(dist[v] > dist[u] + G[i].w) {
dist[v] = dist[u] + G[i].w;
}
}
for(int i = 0;i < G.size();i++) { //此题可以省略
int u,v;
u = G[i].u,v = G[i].v;
if(dist[v] > dist[u] + G[i].w) {
printf("有环!\n");
}
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m) && n && m) {
make_G();
bellman_ford();
printf("%d\n",dist[n]);
}
return 0;
}#include
#include
#include
#include
using namespace std;
const int MAX = 1e7;
int n,m,dist[110];
struct node
{
int v,w;
node(int vv,int ww) : v(vv),w(ww) {}
node() {}
bool operator < (const node &a) const
{
return w > a.w;
}
};
vector G[110];
void make_G()
{
int st,ed,c;
for(int i = 1;i <= n;i++) {
dist[i] = MAX;
G[i].clear();
}
for(int i = 0;i < m;i++) {
scanf("%d%d%d",&st,&ed,&c);
G[st].push_back(node (ed,c));
G[ed].push_back(node (st,c));
}
}
void spfa()
{
priority_queue qe;
int updataTimes[110];
memset(updataTimes,0,sizeof(updataTimes));
node p = node (1,0);
qe.push(p);
dist[p.v] = 0;
while(!qe.empty()) {
p = qe.top();
qe.pop();
for(int i = 0;i < G[p.v].size();i++) {
node q = G[p.v][i];
if(dist[q.v] > dist[p.v] + q.w) {
dist[q.v] = dist[p.v] + q.w;
qe.push(node (q.v,dist[q.v]));
if(++ updataTimes[q.v] >= n) { //更新次数超过n次,有环
printf("有环\n");
}
}
}
}
printf("%d\n",dist[n]);
}
int main()
{
while(~scanf("%d%d",&n,&m) && n && m) {
make_G();
spfa();
}
return 0;
}#include
#include
#include
#include
using namespace std;
const int MAX = 1 << 30;
int n,m,path[110][110];
void make_G()
{
int st,ed,c;
for(int i = 1;i <= n;i++) {
for(int j = 1;j <= n;j++) {
path[i][j] = MAX;
}
}
for(int i = 0;i < m;i++) {
scanf("%d%d%d",&st,&ed,&c);
path[st][ed] = path[ed][st] = c;
}
}
void floyd()
{
for(int k = 1;k <= n;k++) { //注意枚举点的循环的位置
for(int i = 1;i <= n;i ++) {
for(int j = 1;j <= n;j++) {
if(path[i][k] == MAX || path[k][j] == MAX) continue;
if(path[i][j] > path[i][k] + path[k][j]) {
path[i][j] = path[i][k] + path[k][j];
}
}
}
}
}
int main()
{
while(~scanf("%d%d",&n,&m) && n && m) {
make_G();
floyd();
printf("%d\n",path[1][n]);
}
return 0;
}