HDU1595---find the longest of the shortest

来源:互联网 发布:亿图数控系统磨床编程 编辑:程序博客网 时间:2024/03/29 13:47

http://acm.hdu.edu.cn/showproblem.php?pid=1595

题目大意:

从城市1到城市n有m条双向路,其中有一条路是坏的,但是我们不知道到底哪条路是坏的。

考虑到最坏情况,我们从城市1走到城市n所需要的最少时间是多少。


解题思路:

起初,想法很单纯,枚举每一条边为坏边,求1到n的最短路,然后在这些最短路中取最大值。

思路是正确的,但是会超时,路径的条数达到100w,每次求最短路的复杂度为O(n),所以总的复杂度是O(n*100w)。

这个复杂度是无法接受的。


后来看了某位牛人的解法,深受启发。

首先假设所有的路径都是好的,求取1到n的最短路,并且记录下最短路路径上的边。

接着,枚举最短路径上的边为坏边,求取1到n的最短路,在最短路中取最大值。

这样,我们就不需要枚举所有的边,而只是枚举最短路上的边,可以大大降低复杂度。


源代码:

#include <iostream>#include<cstdio>#include<cstring>#include<cstdlib>#include<algorithm>#include<vector>using namespace std;const int maxn=1005;const int maxm=1000005;const int INF=99999999;int first[maxn];int next[maxm],to[maxm],v[maxm],ecnt;int dis[maxn],que[maxn*maxn],vis[maxn],pre[maxn],key[maxn];int n,m,ans;vector<int> vec;inline void add(int a,int b,int c){    to[ecnt]=b;    v[ecnt]=c;    next[ecnt]=first[a];    first[a]=ecnt++;    to[ecnt]=a;    v[ecnt]=c;    next[ecnt]=first[b];    first[b]=ecnt++;    return;}inline void init(){    for(int i=1;i<=n;i++)    {        dis[i]=INF;        vis[i]=0;    }}int spfa(){    init();    dis[1]=0;    vis[1]=1;    int f=0,r=1;    que[f]=1;    while(f<r)    {        int now=que[f++];        vis[now]=0;        for(int i=first[now];i!=-1;i=next[i])        {            if(v[i]==0) continue;            int kid=to[i];            if(dis[now]+v[i]<dis[kid])            {                pre[kid]=now;       //记录下父亲节点                key[kid]=i;         //记录下边                dis[kid]=dis[now]+v[i];                if(!vis[kid])                {                    vis[kid]=1;                    que[r++]=kid;                }            }        }    }    return dis[n];}void solve(){    ans=0;    spfa();     //先跑最短路求取最短路径    vec.clear();    int now=n;    while(now!=1)    {        vec.push_back(key[now]);        now=pre[now];    }    int len=vec.size();    for(int i=0;i<len;i++)  //枚举最短路径上的边    {        int b=vec[i];        int t=v[b];        v[b]=v[b^1]=0;        ans=max(spfa(),ans);        v[b]=v[b^1]=t;    }    printf("%d\n",ans);    return;}int main(){//    freopen("in.txt","r",stdin);    while(scanf("%d%d",&n,&m)==2)    {        ecnt=0;        memset(first,-1,sizeof(first));        while(m--)        {            int a,b,c;            scanf("%d%d%d",&a,&b,&c);            add(a,b,c);        }        solve();    }    return 0;}


原创粉丝点击