【Dijkstra】-LightOJ-1002-Country Roads

来源:互联网 发布:中网络电视台 编辑:程序博客网 时间:2024/06/06 19:19

题目链接:http://lightoj.com/volume_showproblem.php?problem=1002

题目描述:将一条路上最大的边称为这条路的花费。选取花费最少的一条路。

解题思路:

改进后的Dijkstra,精髓在于这句话:

ans[i]=min(ans[i],max(ans[st],cost[st][i]));

因为ans[i]是ans[st]所能连接到的下一个节点,如果cost[i][j]比ans[st]大的话,就可以替代ans[st]而成为ans[i]的值了。又因为我们要选取若干个ans[i]中最小的,所以前面加min

通过这道题应该反思一下Dijkstra,我觉得Dijkstra蕴含两种基本思想:

①贪心。每次都选出距离起点最短的点A,难道还能有比这更短的路径到A么?这应该算是贪心

②DP。或者说是递推,即上一个节点的答案通过一定规律传递给下一个节点,对下一个节点产生无后效性的作用。就像这道题,当前点和上一点是有关系的

比赛时候一片头晕,看来功底不够,后来慢慢想出来的 = =

唉,差得远啊~

AC代码:

#include <iostream>#include <cstring>#include <cstdio>using namespace std;const int INF=9999999;int N;int cost[550][550],ans[550],vis[550];void reset(){    int i,j;    for(i=0;i<550;i++)        for(j=0;j<550;j++)            cost[i][j]=INF;    for(i=0;i<550;i++)        cost[i][i]=0;}void dijkstra(int st){    memset(ans,0,sizeof(ans));    memset(vis,0,sizeof(vis));    int i,j,p;    for(i=0;i<N;i++)        ans[i]=cost[st][i];    vis[st]=1;    while(1)    {        int minans=INF;        for(i=0;i<N;i++)        {            if(ans[i]<minans&&!vis[i])            {                minans=ans[i];                p=i;            }        }        if(minans==INF)break;        vis[p]=1;        st=p;        for(i=0;i<N;i++)        {            ans[i]=min(ans[i],max(ans[st],cost[st][i]));        }    }}int main(){    //freopen("A_input.txt","r",stdin);    int T,M,u,v,w,i,st,cc=1;    cin>>T;    while(T--)    {        reset();        cin>>N>>M;        while(M--)        {            cin>>u>>v>>w;            cost[u][v]=cost[v][u]=min(cost[u][v],w);        }        cin>>st;        dijkstra(st);        cout<<"Case "<<cc<<":"<<endl;        cc++;        for(i=0;i<N;i++)        {            if(ans[i]==INF)                cout<<"Impossible"<<endl;            else                cout<<ans[i]<<endl;        }    }    return 0;}

AC截图:



0 0
原创粉丝点击