图论——寻找最短路径路线的两种算法

前言:关于找到最短路径上经过的边有两种方法
一种是从起点出发找一次最短路径,再从终点出发找一次最短路径
另一种是在找最短路径时标记下一个点


例题1:可怜的草坪

题目描述
小C的大学很大,从寝室到食堂要走很长一段路,很多的草坪位于这些路上。大家从寝室出发时,都喜欢从走最少的路达到食堂,哪些位于最短路上的草坪都要被踩踏,小C希望你帮他算算,有多少段草坪会经常被踩踏?
输入 输入第一行,两个整数n,m。其中1为寝室,n为食堂。 接下来m行,每行三个整数a,b,c,表示有段草坪从a到b,长度为c。 输出 输出最短的距离是多少和m段草坪中有多少段经常被踩踏。

#include
using namespace std;
const int INF=10005;
const int MAX_V=20005;
const int MAX_N=200005;
struct edge{int to,cost;};
typedef pair<int,int>P;
vectorG[MAX_N];
vectorH[MAX_N];
int d[MAX_V],f[MAX_V];
int v;
void dijikstra(int s){
    priority_queuevector

,greater

>que; fill(d,d+v,INF); d[s]=0; que.push(P(0,s)); while(!que.empty()){ P p=que.top();que.pop(); int v1=p.second; if(d[v1]continue; for(int i=0;iif(d[e.to]>d[v1]+e.cost){ d[e.to]=d[v1]+e.cost; que.push(P(d[e.to],e.to)); } } } } void dijikstra1(int s){ priority_queuevector

,greater

>que; fill(f,f+v,INF); f[s]=0; que.push(P(0,s)); while(!que.empty()){ P p=que.top();que.pop(); int v1=p.second; if(f[v1]continue; for(int i=0;iif(f[e.to]>f[v1]+e.cost){ f[e.to]=f[v1]+e.cost; que.push(P(f[e.to],e.to)); } } } } int main(){ int n; cin>>v>>n; for(int i=0;iint a,b,c; scanf("%d%d%d",&a,&b,&c); a=a-1;b=b-1; edge e,e2; e.to=b;e.cost=c; e2.to=a;e2.cost=c; G[a].push_back(e); H[b].push_back(e2); } dijikstra(0); dijikstra1(v-1); int ans=d[v-1]; printf("%d ",ans); int cnt=0; for(int i=0;ifor(int j=0;jif(e.cost+d[i]+f[e.to]==ans)cnt++; } } printf("%d",cnt); return 0; }

例题2:奶牛的延时计划

题目描述:
Lay博士每天早上都要从家到谷仓.他的农场里有N块土地,编号1~N,Lay博士的家在1号,谷仓在N号.有M条双向路径连接它们,且没有重边,经过每条路都要一定时间.Lay博士智商非常高,所以他每次都会走最短的路线,使到达谷仓时间最短.
Lay博士的奶牛都很调皮,想使Lay博士到达谷仓尽可能晚.它们计划在M条路上的某一条路上铺设草堆,使通过这条边的时间加倍.奶牛们想选择一条边,使Lay博士延迟到达谷仓的时间尽可能大.

输入: 两个整数,N(1<=N<=100),M(1<=M<=10000).
接下来M行,每行三个整数a,b,c表示a到b之间的路径,通过的时间为c(1<=c<=106).
输出:输出一个整数,表示奶牛们最多能使Lay博士延迟的时间.

贴上hqz大犇的代码(解法二)

#include
#include
#include
#define M 105
#define INF 0x3f3f3f3f
#define FOR(i,a,b) for(int i=(a);i<=(b);i++)
using namespace std;int n,m,first=1,ans;int pre[M],dis[M],cost[M][M];bool mark[M];queue<int>Q;vector<int>edge[M];int SPFA() {while(!Q.empty())Q.pop();
    memset(dis,63,sizeof(dis));
    memset(mark,0,sizeof(mark));
    Q.push(1);mark[1]=1;dis[1]=0;pre[1]=0;
    while(!Q.empty()) {
        int now=Q.front();
        Q.pop();
        mark[now]=0;
        FOR(i,0,edge[now].size()-1){
            int to=edge[now][i];
            if(dis[to]>dis[now]+cost[to][now]) {
                if(first) pre[to]=now;
                dis[to]=dis[now]+cost[now][to];
                if(!mark[to]) {
                    mark[to]=1;
                    Q.push(to);
                }
            }
        }
    }
    return dis[n];
}

int main(){
    scanf("%d%d",&n,&m);
    FOR(i,1,m){
        int s,t,v;
        scanf("%d%d%d",&s,&t,&v);
        edge[s].push_back(t);
        edge[t].push_back(s);
        cost[s][t]=v,cost[t][s]=v;
    }
    int primor_way=SPFA();
    first=0;
    for(int x=n;;x=pre[x]){
        if(pre[x]==0) break;
        cost[pre[x]][x]=cost[x][pre[x]]=2*cost[x][pre[x]];
        int res=SPFA();
        cost[pre[x]][x]=cost[x][pre[x]]=cost[x][pre[x]]/2;
        ans=max(ans,res-primor_way);
    }
    printf("%d\n",ans);
}

你可能感兴趣的:(——图论)