北大3268题

题目链接:http://acm.pku.edu.cn/JudgeOnline/problem?id=3268

1,题意的关键是求出一个点到其它所有点的最短路径和其它点到这点的最短路径,最容易想到的是用Floyd算法求任意两点的最短路径,但是复杂度是O(n^3)会超时。

2,用Dijkstra可以在O(n^2)的时间内求出一点到其它所有点的最短路径,如果图是无向图,或者说是任意两点彼此相互到达路径长度相同的有向图,那么它也就求出了所有替他点到这一点的最短路径。但是题目中所说的是两点相互到达路径长度并不相等的情况,求出所有点到达一个点的最短路径呢?

3,这里用到一个技巧,没有太想明白:求点x到其它点的最短路径直接用Dijkstra;求其他点到x的最短路径需要对原图做一下处理,将两点间的路径长度彼此交换,然后在用Dijkstra。

#include <iostream>
using namespace std;

#define MAX 1001

#define INF 1000000

struct Graph
{
 int v_num;
 int e_num;
 bool find[MAX];
 int dist[MAX];
 int arc[MAX][MAX];
};
/*Graph g;
int main()
{
 freopen("in.txt","r",stdin);
 int i,j,k,x,m,n,w;
 while(cin >> g.v_num >> g.e_num >> x)
 {
  for(i = 1;i <= g.v_num;++i)
  {
   for(j = 1;j <= g.v_num;++j)
    if(i == j)
     g.arc[i][j] = 0;
    else
     g.arc[i][j] = INF;
  }

  for(i = 0;i < g.e_num;++i)
  {
   cin >> m >> n >> w;
   g.arc[m][n] = w;
  }

  for(i = 1;i <= g.v_num;++i)
  {
   for(j = 1;j <= g.v_num;++j)
   {
    for(k = 1;k <= g.v_num;++k)
    {
     if(g.arc[j][i] + g.arc[i][k] < g.arc[j][k])
      g.arc[j][k] = g.arc[j][i] + g.arc[i][k];
    }
   }
  }

  m = g.arc[1][x] + g.arc[x][1];
  for(i = 2;i <= g.v_num;++i)
  {
   if(i != x)
   {
    n = g.arc[i][x] + g.arc[x][i];
    if(n > m)
     m = n;
   }
  }
  cout << m << endl;
 }
 return 0;
}*/
Graph g;
int i,j,k,x,m,n,w,min,dist[MAX];

void Dijkstra()
{
 for(i = 1;i <= g.v_num;++i)
 {
  g.find[i] = false;
  g.dist[i] = g.arc[x][i];
 }

 g.dist[x] = 0;
 g.find[x] = true;

 for(i = 1;i < g.v_num;++i)
 {
  min = INF;
  for(j = 1;j <= g.v_num;++j)
  {
   if(!g.find[j] && g.dist[j] < min)
   {
    min = g.dist[j];
    k = j;
   }
  }
  g.find[k] = true;
  for(j = 1;j <= g.v_num;++j)
  {
   if(g.arc[k][j] != INF)
   {
    if(!g.find[j] && g.dist[j] > g.dist[k] + g.arc[k][j])
     g.dist[j] = g.dist[k] + g.arc[k][j];
   }
  }
 }
}

int main()
{
 freopen("in.txt","r",stdin);
 while(cin >> g.v_num >> g.e_num >> x)
 {
  for(i = 1;i <= g.v_num;++i)
  {
   for(j = 1;j <= g.v_num;++j)
    g.arc[i][j] = INF;
   g.arc[i][i] = 0;
  }

  for(i = 1;i <= g.e_num;++i)
  {
   cin >> m >> n >> w;
   g.arc[m][n] = w;
  }

  Dijkstra();
  for(i = 1;i <= g.v_num;++i)
   dist[i] = g.dist[i];

  for(i = 1;i <= g.v_num;++i)
  {
   for(j = i+1;j <= g.v_num;++j)
   {
    m = g.arc[i][j];
    g.arc[i][j] = g.arc[j][i];
    g.arc[j][i] = m;
   }
  }
  Dijkstra();

  m = dist[1] + g.dist[1];
  for(i = 2;i <= g.v_num;++i)
  {
   n = dist[i] + g.dist[i];
   if(n > m)
    m = n;
  }
  cout << m << endl;
 }
 return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值