Dijkstra POJ3268 Silver Cow Party解题报告

来源:互联网 发布:数控车床编程培训教程 编辑:程序博客网 时间:2024/06/05 00:46

思路:去X的路径Dij()求一次最短路径,回的路径Dij()求一次最短路径。两次最短路径相加,最后遍历寻找答案。
需建立去、回两个图。
数据太弱,没有队列优化,O(V^2)依然47ms AC

#include <iostream>#include<cstdio>#include<cstring>#define MAXN 1005#define INF 0xffffffusing namespace std;int farms,paths,X,G1[MAXN][MAXN],G2[MAXN][MAXN];int dis[MAXN];//X到每个点的距离int vis[MAXN];//vis[i]=1表示点j已经被松弛int ans[MAXN];//每个点的来回距离之和void dij(int G[MAXN][MAXN]){    //初始化    memset(vis,0,sizeof(vis));    for(int i=1;i<=farms;i++) dis[i]=G[X][i];    dis[X]=0;vis[X]=1;    int minVertex=0,minDis;    for(int i=1;i<=farms;i++){        //寻找边数为i的路径中的最短距离minDis,及其顶点minVertex        minDis=INF;        for(int j=1;j<=farms;j++){            if(!vis[j]&&dis[j]<minDis){            minDis=dis[j];            minVertex=j;            }        }        vis[minVertex]=1;        //对minVertex的邻边进行松弛        for(int j=1;j<=farms;j++){            if(!vis[j]&&dis[j]>dis[minVertex]+G[minVertex][j])                //!vis[j]:说明点j还没有被松弛;dis[j]>dis[minVertex]+G[minVertex][j]表示点j可以被松弛                dis[j]=dis[minVertex]+G[minVertex][j];        }    }}int main(){    freopen("input.txt","r",stdin);    freopen("output.txt","w",stdout);    while(cin>>farms>>paths>>X){            for(int i=1;i<=farms;i++){               for(int j=1;j<=farms;j++){               G1[i][j]=(i==j)?0:INF;//图-去               G2[i][j]=(i==j)?0:INF;//图-回               }            }            for(int i=1;i<=paths;i++){                int a,b,cost;                scanf("%d%d%d",&a,&b,&cost);                G1[a][b]=cost;                G2[b][a]=cost;            }            memset(ans,0,sizeof(ans));            dij(G1);            for(int i=1;i<=farms;i++)ans[i]+=dis[i];                         dij(G2);            for(int i=1;i<=farms;i++) ans[i]+=dis[i];            int _max=0;            for(int i=1;i<=farms;i++) _max=max(_max,ans[i]);            cout<<_max<<endl;    }    return 0;}

如果用Bellman-ford的O(E*V)时间复杂度,会更快,16ms。

#include <stdio.h>#include <string.h>#include #define maxn 1005using namespace std;struct Edge{    int s, e;    int v;}e[100006];int dis1[maxn];int dis2[maxn];int n, m, x;void Bellman(int* dis){    memset(dis, 0x3f, sizeof(dis1));    dis[x] = 0;    for (int i = 1; i < n; i++)    {        int hasrelax = false;      //如果没有松弛过程了 就代表求到了最短路直接跳出        for (int j = 1; j <= m; j++)        {            int u = e[j].s;            int v = e[j].e;            int t = e[j].v;            if (dis[v] > dis[u]+t)            {                dis[v] = dis[u]+t;                hasrelax = true;            }        }        if (hasrelax == false) break;    }}int main(){    while (scanf("%d %d %d", &n, &m, &x) != EOF)    {        int u, v, t;        for (int i = 1; i <= m; i++)        {            scanf("%d %d %d", &u, &v, &t);            e[i].s = u;            e[i].e = v;            e[i].v = t;        }        Bellman(dis1);        for (int i = 1; i <= m; i++)            swap(e[i].s, e[i].e);      //将边的方向反向        Bellman(dis2);                 //求回去的最短路        int ans = 0;        for (int i = 1; i <= n; i++)            ans = max(ans, dis1[i]+dis2[i]);        printf("%d\n", ans);    }    return 0;}
0 0