hdu 1595 find the longest of the shortest ( spfa + 枚举 )

1 解题思路

1.1 题目大意

    给出一个无向图,Marica在结点1,Mirko在结点n,其中有一条边损坏了,但并不知道是哪条,Marica选的路一定是最短路,求最坏情况下Marica要走的路程是多长。

1.2 题目分析

    一开始我通过枚举每条边为坏边,将其设为不可达,然后求1-N的最短距离,最后取一个最大值,结果超时了。然后才想到如果我将不是最短路径上的边设为不可达对最短距离没有影响,做了很多无用功,于是改为:求一次最短距离,然后记下这条路径。然后依次枚举这条路径上的边为坏边(即不可达),求最短路径,取最大值,700多毫秒过了。

2:算法时间分析

    本题的时间复杂度为O(kE)。(k<<V)。

3:代码

#include<stdio.h>

#include<string.h>

#include<queue>

using namespace std;

#define MAXV 1010

#define MAXE 1000000

#define MAXINT 99999999

typedef struct

{

       int from;

       int to;

       int weight;

       int next;

}Edge;

int nv, ne;

int dis[MAXV], vis[MAXV], p[MAXV], index[MAXV];

Edge edge[MAXE];

 

void init()

{

       ne=0;

       memset(index,-1, sizeof(index));

}

void insert_edge(int s, int t, int w)

{

       edge[ne].from=s;

       edge[ne].to=t;

       edge[ne].weight=w;

       edge[ne].next=index[s];

       index[s]=ne;

       ne++;

       edge[ne].from=t;

       edge[ne].to=s;

       edge[ne].weight=w;

       edge[ne].next=index[t];

       index[t]=ne;

       ne++;

}

int spfa(int s, int t)

{

       int i, u,v, w;

       int count=0;

       queue<int>que;

       for(i=0;i<=nv;i++)

       {

              dis[i]=MAXINT;

              vis[i]=0;

              p[i]=-1;

       }

 

       dis[s]=0;

       que.push(s);

       vis[s]=1;

       while(!que.empty())

       {

              u=que.front();

              que.pop();

              vis[u]=0;

              for(i=index[u];i!=-1;i=edge[i].next)

              {

                     v=edge[i].to;

                     w=edge[i].weight;

                     if(dis[v]>dis[u]+w)

                     {

                            dis[v]=dis[u]+w;

                            p[v]=u;

                            if(!vis[v])

                            {

                                   que.push(v);

                                   vis[v]=1;

                            }

                     }

              }

       }

       return dis[t];

}

int main()

{

       //freopen("test.txt","r", stdin);

       int m;

       while(EOF!=scanf("%d%d",&nv, &m))

       {

              int i, j, max, pa[MAXV], path[MAXV];

              init();

              while(m--)

              {

                     inta, b, c;

                     scanf("%d%d%d",&a, &b, &c);

                     insert_edge(a,b, c);

              }

 

              max=spfa(1,nv);

              memset(pa,-1, sizeof(pa));

              memset(path,-1, sizeof(path));

              //保存父亲数组

              for(i=1;i<=nv;i++)

                     pa[i]=p[i];

              //找出最短路径上的边在edge数组里的下标号

              int count=0;

              for(i=nv;i!=-1;i=pa[i])

              {

                     for(j=index[i];j!=-1;j=edge[j].next)

                     {

                            if(edge[j].to==p[i])

                            {

                                   path[count++]=j;

                                   break;

                            }

                     }

              }

              //每次删除一条最短路径上的边,求一下最短路径,与前面求出的最长的最短路径比较,取最大值

              int ret, tp;

              for(i=0;i<count;i++)

        {

           tp=edge[path[i]].weight;

           edge[path[i]^1].weight=MAXINT;

           edge[path[i]].weight=MAXINT;

           ret=spfa(1, nv);

           edge[path[i]^1].weight=tp;

           edge[path[i]].weight=tp;

            if(ret<MAXINT&& max<ret)

               max=ret;

        }

 

              printf("%d\n",max);

       }

       return 0;

}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值