最短路dijkstra入门题

HDU 1874 畅通工程续

水dijkstra

View Code
#include<stdio.h>
#include<string.h>
#define INF 1000000
#define maxn 201
int adj[maxn][maxn],dis[maxn];//pre[maxn]
bool vis[maxn];
int n ,m;
int dijkstra(int src, int dest)
{
    int i ,j, k, u, min;
    for(i=0;i<n;i++)
    {
        vis[i]=0;
        dis[i]=adj[src][i];
        //if(src != i && dis[src] < INF)pre[i] = src;
        //else pre[i] = -1;
    }
    vis[src]=1;dis[src]=0;
    for(i=0;i<n;i++)
    {
        min = INF;
        for(j=0;j<n;j++)
        {
            if(!vis[j]&&min > dis[j])
            {
                min = dis[j];
                u = j;
                //pre[j] = src;
            }
        }
        vis[u]=1;
        for(j=0;j<n;j++)
        {
            if(!vis[j] && dis[u] + adj[u][j] < dis[j]&&adj[u][j]!=INF)
            {
                dis[j] = dis[u] + adj[u][j];
                //pre[j] = u;
            }
        }
    }
    return dis[dest] < INF? dis[dest]:  -1;
}
void init()
{
    int i ,j;
    for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
        {
            if(i==j)adj[i][j]=0;
            else adj[i][j]=INF;
        }
    }
}
int main()
{
    int x, y ,w;
    while(~scanf("%d%d",&n,&m)&&n)
    {
        init();
        while(m--)
        {
            scanf("%d%d%d",&x,&y,&w);
            if(adj[x][y] > w)
            {
                adj[x][y]=w;
                adj[y][x]=w;
            }
        }
        int s,t;
        scanf("%d%d",&s,&t);
        printf("%d\n",dijkstra(s,t));
    }
    return 0;
}

 

HDU 2112 HDU Today

字符串处理,可以人工处理,也可以用STL中的map,个人觉得人工处理不麻烦,map麻烦死了,就自己处理了

然后 dijkstra水一个

View Code
#include<stdio.h>
#include<string.h>
#define INF 1000000
#define maxn 201
int adj[maxn][maxn],dis[maxn];//pre[maxn]
bool vis[maxn];
int n ,m;
int dijkstra(int src, int dest)
{
    int i ,j, k, u, min;
    for(i=0;i<n;i++)
    {
        vis[i]=0;
        dis[i]=adj[src][i];
        //if(src != i && dis[src] < INF)pre[i] = src;
        //else pre[i] = -1;
    }
    vis[src]=1;dis[src]=0;
    for(i=0;i<n;i++)
    {
        min = INF;
        for(j=0;j<n;j++)
        {
            if(!vis[j]&&min > dis[j])
            {
                min = dis[j];
                u = j;
                //pre[j] = src;
            }
        }
        vis[u]=1;
        for(j=0;j<n;j++)
        {
            if(!vis[j] && dis[u] + adj[u][j] < dis[j]&&adj[u][j]!=INF)
            {
                dis[j] = dis[u] + adj[u][j];
                //pre[j] = u;
            }
        }
    }
    return dis[dest] < INF? dis[dest]:  -1;
}
void init()
{
    int i ,j;
    for(i=0;i<n;i++)
    {
        for(j=0;j<n;j++)
        {
            if(i==j)adj[i][j]=0;
            else adj[i][j]=INF;
        }
    }
}
int main()
{
    int x, y ,w;
    while(~scanf("%d%d",&n,&m)&&n)
    {
        init();
        while(m--)
        {
            scanf("%d%d%d",&x,&y,&w);
            if(adj[x][y] > w)
            {
                adj[x][y]=w;
                adj[y][x]=w;
            }
        }
        int s,t;
        scanf("%d%d",&s,&t);
        printf("%d\n",dijkstra(s,t));
    }
    return 0;
}

 

HDU 2680 Choose the best route
是单向图WA了好几次才发现;

题目起点有好几个,终点就一个;

方法一:题目顶点1,2,3......n,自己设置个0顶点作为源点,让0点与所有起点连接,权值为0,即adj[0][起点]=0,别忘了初始化adj时把0也初始化;

View Code
#include<stdio.h>
#include<string.h>
#define maxn 1001
#define INF 100000000

int dis[maxn],adj[maxn][maxn];
bool vis[maxn];
int n, m, s, t;

void dijkstra(int v)
{
    int i, j, k, min, u;
    for(i=1;i<=n;i++)
    {
        dis[i]=adj[v][i];
        vis[i]=0;
    }
    vis[v]=1;dis[v]=0;
    for(i=1;i<=n;i++)
    {
        min = INF;
        for(j=1;j<=n;j++)
        {
            if(min > dis[j]&&!vis[j])
            {
                min = dis[j];
                u = j;
            }
        }
        if(min == INF)break;
        vis[u]=1;
        for(j=1;j<=n;j++)
        {
            if(dis[u] + adj[u][j] < dis[j]&&!vis[j])
            {
                dis[j] = dis[u] + adj[u][j];
            }
        }
    }
}
int main()
{
    int i, j, x, y, w;
    while(~scanf("%d%d%d",&n,&m,&t))
    {
        for(i=0;i<=n;i++)
            for(j=0;j<=n;j++)
                adj[i][j]=INF;
        while(m--)
        {
            scanf("%d%d%d",&x,&y,&w);
            if(adj[x][y] > w)adj[x][y] = w;
        }
        scanf("%d",&m);
        while(m--)
        {
            scanf("%d",&x);
            adj[0][x]=0;
        }
        dijkstra(0);
        if(dis[t]== INF)printf("-1\n");
        else printf("%d\n",dis[t]);
    }
    return 0;
}

方法二:把终点作为源点写个逆向的dijkstra

可以读入边时就反 一下

View Code
#include<stdio.h>
#include<string.h>
#define maxn 1001
#define INF 100000000

int dis[maxn],adj[maxn][maxn];
bool vis[maxn];
int n, m, s, t;

void dijkstra(int v)
{
    int i, j, k, min, u;
    for(i=1;i<=n;i++)
    {
        dis[i]=adj[v][i];
        vis[i]=0;
    }
    vis[v]=1;dis[v]=0;
    for(i=1;i<=n;i++)
    {
        min = INF;
        for(j=1;j<=n;j++)
        {
            if(min > dis[j]&&!vis[j])
            {
                min = dis[j];
                u = j;
            }
        }
        if(min == INF)break;
        vis[u]=1;
        for(j=1;j<=n;j++)
        {
            if(dis[u] + adj[u][j] < dis[j]&&!vis[j])
            {
                dis[j] = dis[u] + adj[u][j];
            }
        }
    }
}
int main()
{
    int i, j, x, y, w;
    while(~scanf("%d%d%d",&n,&m,&t))
    {
        for(i=0;i<=n;i++)
            for(j=0;j<=n;j++)
                adj[i][j]=INF;
        while(m--)
        {
            scanf("%d%d%d",&x,&y,&w);
            if(adj[y][x] > w)adj[y][x] = w; //注意反了
        }
        scanf("%d",&m);
        int ans = INF;
        dijkstra(t);
        while(m--)
        {
            scanf("%d",&x);
            if(dis[x]< ans)ans=dis[x];
        }
        if(ans== INF)printf("-1\n");
        else printf("%d\n",ans);
    }
    return 0;
}

也可以在dijkstra里面反一下

View Code
#include<stdio.h>
#include<string.h>
#define maxn 1001
#define INF 100000000

int dis[maxn],adj[maxn][maxn];
bool vis[maxn];
int n, m, s, t;

void dijkstra(int v)
{
    int i, j, k, min, u;
    for(i=1;i<=n;i++)
    {
        dis[i]=adj[i][v]; //注意adj下标反了
        vis[i]=0;
    }
    vis[v]=1;dis[v]=0;
    for(i=1;i<=n;i++)
    {
        min = INF;
        for(j=1;j<=n;j++)
        {
            if(min > dis[j]&&!vis[j])
            {
                min = dis[j];
                u = j;
            }
        }
        if(min == INF)break;
        vis[u]=1;
        for(j=1;j<=n;j++)
        {
            if(dis[u] + adj[j][u] < dis[j]&&!vis[j]) //注意adj下标反了
            {
                dis[j] = dis[u] + adj[j][u];     //注意adj下标反了
            }
        }
    }
}
int main()
{
    int i, j, x, y, w;
    while(~scanf("%d%d%d",&n,&m,&t))
    {
        for(i=0;i<=n;i++)
            for(j=0;j<=n;j++)
                adj[i][j]=INF;
        while(m--)
        {
            scanf("%d%d%d",&x,&y,&w);
            if(adj[x][y] > w)adj[x][y] = w;
        }
        scanf("%d",&m);
        int ans = INF;
        dijkstra(t);
        while(m--)
        {
            scanf("%d",&x);
            if(dis[x]< ans)ans=dis[x];
        }
        if(ans== INF)printf("-1\n");
        else printf("%d\n",ans);
    }
    return 0;
}

 

HDU 2066  一个人的旅行

这题终点起点都有多个,可以用上一题的方法一,设置虚拟起点0和虚拟终点1001

View Code
#include<stdio.h>
#include<string.h>
#define maxn 1003
#define INF 100000000

int n, m;
bool vis[maxn];
int adj[maxn][maxn],dis[maxn],pre[maxn];

int dijstra(int scr, int dest)
{
    int i ,j, k, u;
    for(i=1;i<=n;i++)
    {
        vis[i]=0;
        dis[i]=adj[scr][i];
    }
    vis[scr]=1;dis[scr]=0;
    for(i=1;i<n;i++)
    {
        int min = INF;
        for(j=1;j<=n;j++)
        {
            if(min > dis[j]&&!vis[j])
            {
                min = dis[j];
                u=j;
            }
        }
        if(min==INF)break;
        vis[u]=1;
        for(j=1;j<=n;j++)
        {
            if(dis[u]+adj[u][j] < dis[j]&&!vis[j])
            {
                dis[j] = dis[u] + adj[u][j];
            }
        }
    }
    return dis[dest] < INF ? dis[dest] : -1;
}
int main()
{
    int x, y, w, i, j, s, t, p, q;
    while(~scanf("%d%d%d",&m,&p,&q))
    {
        n=1001;
        for(i=0;i<=n+2;i++)
        {
            for(j=0;j<=n+2;j++)
            {
                adj[i][j]=INF;
            }
        }
        while(m--)
        {
            scanf("%d%d%d",&x,&y,&w);
            if(adj[x][y] > w)
            {
                adj[x][y]=w;
                adj[y][x]=w;
            }
        }
        while(p--)
        {
            scanf("%d",&s);
            adj[0][s]=0;
        }
        while(q--)
        {
            scanf("%d",&t);
            adj[t][1001]=0;
        }
        printf("%d\n",dijstra(0, 1001));
    }
    return 0;
}

 

 POJ 2240 Arbitrage

floyd水题

View Code
#include<stdio.h>
#include<string.h>
using namespace std;
int n, m;
double adj[32][32];
char str[32][101];
char s[101];
int find(char s[])
{
    int i;
    for(i=1;i<=n;i++)
        if(strcmp(s,str[i])==0)return i;
}
int floyd()
{
    int i,j,k;
    for(k=1;k<=n;k++)
    {
        for(i=1;i<=n;i++)
        {
            for(j=1;j<=n;j++)
            {
                    if(adj[i][j]<adj[i][k]*adj[k][j])
                        adj[i][j]=adj[i][k]*adj[k][j];
                if(adj[1][1]>1)return 1;
            }
        }
    }
    return 0;
}
int main()
{
    int i, j, x, y, X=1;
    double w;
    while(~scanf("%d",&n)&&n)
    {
        for(i=1;i<=n;i++)
            scanf("%s",str[i]);
        memset(adj,0,sizeof(adj));
        scanf("%d",&m);
        while(m--)
        {
            scanf("%s",s);x=find(s);
            scanf("%lf",&w);
            scanf("%s",s);y=find(s);
            adj[x][y]=w;
        }
        printf("Case %d: ",X++);
        floyd()?puts("Yes"):puts("No");
    }
    return 0;
}

 

posted @ 2012-07-23 22:26  To be an ACMan  Views(556)  Comments(0Edit  收藏  举报