MCS 最短路#2 dijkstra

题目链接,可TP

一开始叫我写博客,其实
这里写图片描述
这博客界面真TM难看,后来发现功能还是蛮好玩的

而我连floyd都还不完全会,早上还在刷DFS的人晚上居然被叫来写迪什么鬼的题解也是心很累啊,不管怎么说,先打两局游戏王压压惊。
下面才不是废话

最短路#2 dijkstra 题解

Problem A

题目大意:
输入两个整数N、M(N<=100,M<=10000),N是点的数量,M是线的数量,可看作无向图,然后输入M行,每行3个数A,B,C,表示从A到B权重为C,求从第1个点到第N个点的最短路
思路:
毫无思路,听方绎杰说就是把昨天写的floyd改成dijkstra就行了。于是,我就把他的代码复制过来了

#include<cstdio>
#include<iostream>
#include<cstring>
using namespace std;
#define MAX 99999999  
//当时这里是7个9,我问为什么不能是8个,于是我改成了8个9

int n,m;
int map[105][105];
int vis[105];
int x[105];

void dijkstra()
{
    int min,i,j,k;
    //初始化
    for(i=0;i<=n;i++)
    {
        vis[i]=0;
        x[i]=map[1][i];
    }
    //标记起点
    vis[1]=1;
    //据说下面的3个for都是按照套路来的
    for(i=0;i<n;i++)
    {
        min=MAX;
        for(j=1;j<=n;j++)
        {
            //找出未标记且路径更短的点
            if(!vis[j]&&x[j]<min)
            {
                k=j;
                min=x[j];
            }
        }
        //标记该点
        vis[k]=1;
        //以该点为中转点寻找更短的路径
        for(j=1;j<=n;j++)
        {
            if(!vis[j]&&(min+map[k][j]<x[j]))
                x[j]=min+map[k][j];
        }
    }
}

int main()
{
    while(~scanf("%d%d",&n,&m),m||n)
    {
        int i,j,k;
        int a,b,c;
        //初始化
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                //自身到自身距离为0
                if(i==j)map[i][j]=0;
                map[i][j]=MAX;
            }
        }
        for(i=0;i<m;i++)
        {
            cin>>a>>b>>c;
            //无向图来回距离相等
            map[a][b]=c;
            map[b][a]=c;
        }
        dijkstra();
        cout<<x[n]<<endl;
    }
    return 0;
}

Problem B

题目大意:
输入两个整数T,N(2<=N<=1000,1 <= T <= 2000),N是点的数量,T是线的数量,可看作无向图,然后输入T行,每行3个数A,B,C,表示从A到B权重为C,求从第N个点到第1个点的最短路
思路:
英语渣在询问了翻译后听说把A的代码直接ctrl c+ctrl v就能过了,因为是无向图系列,1到N和N到1值是一样的,所以题目大意都是ctrl c+ctrl v的。我差点就信了,然后就RE了2次

#include <iostream>
#include <cstring>
#include <cstdio>
#define MAX_WAY 9999999

using namespace std;

int T,N;
int vis[1005];
int field[1005][1005];
int L[1005];

void dijkstra()
{
    int v,w,k,Min;
    //初始化
    for( v = 1; v <= N; v++ )
    {
        vis[v] = 0;
        L[v] = field[1][v];
    }
    //标记起点
    vis[1] = 1;
    //套路
    for( v = 1; v < N; v++ )
    {
        Min = MAX_WAY;
        //找出未标记且路径更短的点
        for( w = 1; w <= N; w++ )
        {
            if( L[w] < Min && !vis[w] )
            {
                k = w;
                Min = L[w];
            }
        }
        //标记该点
        vis[k] = 1;
        //以该点为中转点寻找更短的路径
        for( w = 1; w <= N; w++ )
        {
            if( !vis[w] && ( Min + field[k][w] < L[w] ))
            {
                L[w] = Min + field[k][w];
            }
        }
    }
}

int main()
{
    while(cin >> T >> N)
    {
        int i,j;
        //初始化
        for( i = 0; i < 1005; i++ )
            for( j = 0; j < 1005; j++ )
            {
                //自身到自身距离为0
                if( i == j ) field[i][j] = 0;
                else field[i][j] = MAX_WAY;
            }
        int A,B,C;
        while( T -- )
        {
            cin >> A >> B >> C;
            if( field[A][B] > C )
            {
                //无向图来回距离相等
                field[A][B] = C;
                field[B][A] = C;
            }
        }
        dijkstra();
        cout<<L[N]<<endl;
    }
    return 0;
}

Problem C

题目大意:
输入一个数,表示有多少组数据,再输入两个整数n、m(1 <= n <= 1000),n是点的数量,m是线的数量,可看作无向图,然后输入m行,每行3个数A,B,C,表示从A到B权重为C,求所有通路上的最短边的最大值。例如对于数据,从1运到3有两种方案
方案1:1-2-3,其中1-2承重为3,2-3承重为5,则可以运送货物的最大重量是3(当大于3时明显1到不了2)
方案2:1-3,可知1-3承重为4,故此路可运送货物的最大重量是4,故答案输出4
思路:
跟着套路走,用Dijkstra算法解之,只是需要把“最短路”的定义稍微改变一下

#include <iostream>  
using namespace std;  
#define MAXV 1010  
#define min(a,b) (a<b?a:b)  

int map[MAXV][MAXV],n,m;  

int dijkstra()
{  
    int vis[MAXV],d[MAXV],i,j,v;  
    初始化
    for(i=1;i<=n;i++)
    {  
        vis[i]=0;  
        //这个时候d不代表从1到n的最短路径,而是最大承载量  
    }  
    //都是套路
    for(i=1;i<=n;i++)
    {  
        int f=-1;  
        for(j=1;j<=n;j++)  
        {  
            f=d[j];  
            v=j;  
        }  
        vis[v]=1;  
        for(j=1;j<=n;j++)  
            if(!vis[j] && d[j]<min(d[v],map[v][j]))
            {  
                //此处条件和赋值是关键
                d[j]=min(d[v],map[v][j]);  
            }  
    }  
    return d[n];  
}  

int main(){  
    int t,i,j,sum,a,b,c;  
    scanf("%d",&sum);  
    for(t=1;t<=sum;t++){  
        scanf("%d%d",&n,&m);  
        //初始化
        for(i=0;i<=n;i++)            
            for(j=0;j<=n;j++)  
                map[i][j]=0;  
        for(i=1;i<=m;i++){  
            scanf("%d%d%d",&a,&b,&c);  
            map[a][b]=map[b][a]=c;  
        }  
        printf("Scenario #%d:\n",t);  
        printf("%d\n\n",dijkstra());  
    }  
    return 0;  
}  

网上有个题解很6 链接可TP

Problem D

题目大意:
输入N,M,X,表示有N个点,M条边,要求各个点到点X往返的最短路径的最大值。可看作有向图,然后输入M行,每行3个数A,B,C,表示从A到B权重为C。注意是有向图所以往返的最短路径可能不同。
思路:
跟着套路走,求两次最短路,第一次求x到其余各点的最短路,第二次求各点到x的最短路,然而我并没有做出来= =。直接贴web题解好了。。

#include <iostream>
#include <cstdio>
#include <string.h>
const int N=1010;
int nfarm,npath,pos;
int map1[N][N],map2[N][N],visted[N];
int dis1[N],dis2[N];
#define MAX 0x7fffffff
void dijkstra(int dis[N],int map[N][N]){
  memset(visted,0,sizeof(visted));
  for(int i=1;i<=nfarm;++i)
      dis[i]=map[pos][i];
  dis[pos]=0;
  visted[pos]=1;
  int newpos=pos;
  for(int i=1;i<=nfarm;++i){
      for(int j=1;j<=nfarm;++j){
          if(!visted[j]&&map[newpos][j]!=MAX&&dis[newpos]+map[newpos][j]<dis[j]){
            dis[j]=dis[newpos]+map[newpos][j];
          }
      }
      int mmin=MAX;
      for(int j=1;j<=nfarm;++j){
          if(!visted[j]&&mmin>dis[j]){
            mmin=dis[j];
            newpos=j;
          }
      }
      visted[newpos]=1;
  }
}
int main(){
    //freopen("11.txt","r",stdin);
    while(~scanf("%d%d%d",&nfarm,&npath,&pos)){
      int x,y,z;
      for(int i=0;i<=nfarm;++i){
          for(int j=0;j<=nfarm;++j){
            map1[i][j]=MAX;
            map2[i][j]=MAX;
          }
      }
      while(npath--){
        scanf("%d%d%d",&x,&y,&z);
        map1[x][y]=z;
        map2[y][x]=z;
      }
      dijkstra(dis1,map1);
      dijkstra(dis2,map2);
      int mmax=0;
     /* for(int i=1;i<=nfarm;++i){
        printf("%d ",dis1[i]);
      }*/
      for(int i=1;i<=nfarm;++i){
        if(dis1[i]+dis2[i]>mmax)
            mmax=dis1[i]+dis2[i];
      }
      printf("%d\n",mmax);
    }
  return 0;
}

话说锐捷崩了怪我咯(#--)/ .

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值