zoukankan      html  css  js  c++  java
  • hdu 1688 Sightseeing (次短路及次短路数)&&pku3255 Roadblocks &&3191 How Many Paths Are There

    hdu1688

    题意:找出从S到F两个点之间的最短路和比最短路长1的次短路的条数之和。

    分析:最短路很好求,关键是次短路,郁闷呀

    不过,如果对最短路的更新距离的过程有更深的认识的话,就好办很多了。

    用一个二维数组记录每一个节点距离起始点的最短距离和次短距离,再开一个二维数组记录路径数

    更新状态时:

     1)新值小于最短路径长:更新最短路径长,计数;次短路径长,计数

    2)新值等于最短路径长:更新最短路径计数

     3)新值大于最短路径长,小于次短路径长:更新次短路径长,计数

    4)新值等于次短路径长:更新次短路径计数

    View Code
    #include<iostream>
    #include<algorithm>
    #include<vector>

    using namespace std;
    const int N = 1001;
    struct node
    {
    int v,w;
    node(){}
    node(int v,int w):v(v),w(w){}
    };
    vector<node> g[N];
    int n,dist[N][2],cnt[N][2];
    bool vis[N][2];
    void Dijkstra(int s)
    {
    for(int i=1;i<=n;i++)
    {
    dist[i][0]=INT_MAX;
    dist[i][1]=INT_MAX;
    }
    memset(vis,false,sizeof(vis));
    dist[s][0]=0;
    cnt[s][0]=1;
    for(int i=0;i<2*n;i++)//每一个节点会被更新俩次,最短和次短,所以是2*n
    {
    int temp=INT_MAX,u=-1,k;
    for(int j=1;j<=n;j++)
    if(!vis[j][0] && dist[j][0]<temp)//对于每一个节点,肯定是先更新最短,再更新次短
    {
    k=0;
    temp=dist[j][0];
    u=j;
    }
    else if(!vis[j][1] && dist[j][1]<temp)
    {
    k=1;
    temp=dist[j][1];
    u=j;
    }
    if(u==-1)
    break;
    vis[u][k]=true;
    vector<node>::iterator it=g[u].begin();
    for(;it!=g[u].end();it++)
    {
    int newdis=dist[u][k]+it->w;
    int v=it->v;
    if(newdis<dist[v][0])
    {
    dist[v][1]=dist[v][0];
    cnt[v][1]=cnt[v][0];
    dist[v][0]=newdis;
    cnt[v][0]=cnt[u][k];
    }
    else if(newdis==dist[v][0])
    cnt[v][0]+=cnt[u][k];
    else if(newdis<dist[v][1])
    {
    dist[v][1]=newdis;
    cnt[v][1]=cnt[u][k];
    }
    else if(newdis==dist[v][1])
    cnt[v][1]+=cnt[u][k];
    }
    }
    }
    int main()
    {
    int T,m,a,b,c;
    int s,t;
    scanf("%d",&T);
    while(T--)
    {
    scanf("%d %d",&n,&m);
    for(int i=1;i<=n;i++)
    g[i].clear();
    for(int i=0;i<m;i++)
    {
    scanf("%d %d %d",&a,&b,&c);
    g[a].push_back(node(b,c));
    }
    scanf("%d %d",&s,&t);
    Dijkstra(s);
    int ans=cnt[t][0];
    if(dist[t][1]==dist[t][0]+1)
    ans+=cnt[t][1];
    printf("%d\n",ans);
    }
    return 0;
    }

    以上解释参考该博客http://www.cppblog.com/Davidlrzh/articles/114788.html

    pku3255 Roadblocks

    题意:求一条次短路,不能等于最短路

    可以分别对1和n进行两次Dijkstra,然后枚举边,产生新的一条路,即两点分别到1和n的距离和加上这条边的距离。

    当然,也可以用上面类似的方法

    方法一
    #include<iostream>
    #include<algorithm>
    #include<string>
    #include<vector>
    using namespace std;
    const int N = 5001;
    struct node
    {
    int v,w;
    node(){}
    node(int v,int w):v(v),w(w){}
    };
    struct edge
    {
    int u,v,w;
    edge(){}
    edge(int u,int v,int w):u(u),v(v),w(w){}
    }e[100001];
    vector<node> g[N];
    int n,dists[N],distt[N];
    bool vis[N];
    void Dijkstra(int dis[],int s)
    {
    for(int i=1;i<=n;i++)
    dis[i]=INT_MAX;
    memset(vis,false,sizeof(vis));
    dis[s]=0;
    for(int i=0;i<n;i++)
    {
    int temp=INT_MAX,u=-1;
    for(int j=1;j<=n;j++)
    {
    if(!vis[j] &&dis[j]<temp)
    {
    temp=dis[j];
    u=j;
    }
    }
    if(u==-1) break;
    vis[u]=true;
    vector<node>::iterator it=g[u].begin();
    for(;it!=g[u].end();it++)
    {
    int newdis=dis[u]+it->w;
    int v=it->v;
    if(newdis<dis[v])
    dis[v]=newdis;
    }
    }
    }
    int main()
    {
    int m,a,b,c,minlen;
    while(scanf("%d %d",&n,&m)==2)
    {
    for(int i=1;i<=n;i++)
    g[i].clear();
    minlen=INT_MAX;
    for(int i=0;i<m;i++)
    {
    scanf("%d %d %d",&a,&b,&c);
    g[a].push_back(node(b,c));
    g[b].push_back(node(a,c));
    e[i]=edge(a,b,c);
    minlen=min(c,minlen);
    }
    Dijkstra(dists,1);
    Dijkstra(distt,n);
    int mins=dists[n],ans=INT_MAX;
    for(int i=0;i<m;i++)
    {
    int temp=dists[e[i].u]+e[i].w+distt[e[i].v];
    if(temp >mins && temp<ans)
    ans=temp;
    temp=dists[e[i].v]+e[i].w+distt[e[i].u];
    if(temp>mins && temp<ans)
    ans=temp;
    }

    printf("%d\n",ans);
    }
    return 0;
    }
    方法二 
    #include<iostream>
    #include<algorithm>
    #include<vector>

    using namespace std;
    const int N = 5001;
    struct node
    {
    int v,w;
    node(){}
    node(int v,int w):v(v),w(w){}
    };
    vector<node> g[N];
    int n,dist[N][2];
    bool vis[N][2];
    void Dijkstra(int s)
    {
    for(int i=1;i<=n;i++)
    {
    dist[i][0]=INT_MAX;
    dist[i][1]=INT_MAX;
    }
    memset(vis,false,sizeof(vis));
    dist[s][0]=0;
    for(int i=0;i<2*n;i++)//每一个节点会被更新俩次,最短和次短,所以是2*n
    {
    int temp=INT_MAX,u=-1,k;
    for(int j=1;j<=n;j++)
    if(!vis[j][0] && dist[j][0]<temp)//对于每一个节点,肯定是先更新最短,再更新次短
    {
    k=0;
    temp=dist[j][0];
    u=j;
    }
    else if(!vis[j][1] && dist[j][1]<temp)
    {
    k=1;
    temp=dist[j][1];
    u=j;
    }
    if(u==-1)
    break;
    vis[u][k]=true;
    vector<node>::iterator it=g[u].begin();
    for(;it!=g[u].end();it++)
    {
    int newdis=dist[u][k]+it->w;
    int v=it->v;
    if(newdis<dist[v][0])
    {
    dist[v][1]=dist[v][0];
    dist[v][0]=newdis;
    }
    else if(newdis<dist[v][1])
    dist[v][1]=newdis;
    }
    }
    }
    int main()
    {
    int m,a,b,c;
    while(scanf("%d %d",&n,&m)==2)
    {
    for(int i=1;i<=n;i++)
    g[i].clear();
    for(int i=0;i<m;i++)
    {
    scanf("%d %d %d",&a,&b,&c);
    g[a].push_back(node(b,c));
    g[b].push_back(node(a,c));
    }
    Dijkstra(1);
    printf("%d\n",dist[n][1]);
    }
    return 0;
    }

    hdu3191 How Many Paths Are There

    几乎一样的题

    View Code
    #include<iostream>
    #include<algorithm>
    #include<string>
    #include<vector>
    using namespace std;
    const int N = 55;
    struct node
    {
    int v,w;
    node(){}
    node(int v,int w):v(v),w(w){}
    };
    vector<node> g[N];
    int n,dist[N][2],cnt[N][2];
    bool vis[N][2];
    void Dijkstra(int s)
    {
    for(int i=0;i<n;i++)
    {
    dist[i][0]=INT_MAX;
    dist[i][1]=INT_MAX;
    }
    memset(vis,false,sizeof(vis));
    memset(cnt,0,sizeof(cnt));
    dist[s][0]=0;
    cnt[s][0]=1;
    for(int i=0;i<2*n;i++)
    {
    int temp=INT_MAX,u=-1,k;
    for(int j=0;j<n;j++)
    {
    if(!vis[j][0] && dist[j][0]<temp)
    {
    k=0;
    u=j;
    temp=dist[j][0];
    }
    else if(!vis[j][1] && dist[j][1]<temp)
    {
    k=1;
    u=j;
    temp=dist[j][1];
    }
    }
    if(u==-1) break;
    vis[u][k]=true;
    vector<node>::iterator it=g[u].begin();
    for(;it!=g[u].end();it++)
    {
    int newdis=dist[u][k]+it->w;
    int v=it->v;
    if(newdis<dist[v][0])
    {
    dist[v][1]=dist[v][0];
    cnt[v][1]=cnt[v][0];
    dist[v][0]=newdis;
    cnt[v][0]=cnt[u][k];
    }
    else if(newdis==dist[v][0])
    cnt[v][0]+=cnt[u][k];
    else if(newdis<dist[v][1])
    {
    dist[v][1]=newdis;
    cnt[v][1]=cnt[u][k];
    }
    else if(newdis==dist[v][1])
    cnt[v][1]+=cnt[u][k];
    }
    }
    }
    int main()
    {
    int s,t,a,b,c,m;
    while(scanf("%d %d %d %d",&n,&m,&s,&t)==4)
    {
    for(int i=0;i<n;i++)
    g[i].clear();
    for(int i=0;i<m;i++)
    {
    scanf("%d %d %d",&a,&b,&c);
    g[a].push_back(node(b,c));
    }
    Dijkstra(s);
    printf("%d %d\n",dist[t][1],cnt[t][1]);
    }
    return 0;
    }



  • 相关阅读:
    10年测试专家深度解读接口测试
    测试技术大牛谈成长经历:一个好的软件测试工程师应该做到这些!
    一位测试老鸟的工作经验分享
    又一名程序员倒下,网友:我们只是新时代农民工
    软件测试工程师这样面试,拿到offer的几率是80%
    App测试流程及测试点(个人整理版)
    自动化测试是什么?
    软件测试工程师的职业技能分析
    月薪15k的测试员需要学习什么技术?
    面向对象
  • 原文地址:https://www.cnblogs.com/nanke/p/2414315.html
Copyright © 2011-2022 走看看