数据结构上机题目--dijkstra

dijkstra:

/*************************************************************************
* author:crazy_石头
* algorithm:Dijkstra
* date:2013/09/29
* 程序功能:最短路
* 算法流程:初始时,S中仅含有源。设u是G的某一个顶点,把从源到u且中间只经过S中顶点的路称为
* 从源到u的特殊路径,并用数组dist记录当前每个顶点所对应的最短特殊路径长度。
* Dijkstra算法每次从V-S中取出具有最短特殊路长度的顶点u,将u添加到S中,
* 同时对数组dist作必要的修改。一旦S包含了所有V中顶点,dist就记录了从源到所有其它顶点之间的
* 最短路径长度。
**************************************************************************/
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cstdlib>

using namespace std;

#define INF 1<<29
#define A system("pause")

const int maxn=1000;

int map[101][101],d[101],mark[101];//d为距离向量;
int pre[maxn];//记录每个节点的前驱最终形成一条路径;
int m,n,s,e;

inline int min(int a,int b)
{
    return a<b?a:b;
}

inline void Dijkstra()
{
    int i,j,k,min;
    memset(mark,0,sizeof(mark));
    for(i=0;i<n;i++)
    {
        d[i]=map[s][i];
        if(d[i]==INF)
            pre[i]==0;
        else
            pre[i]=s;
    }
    d[s]=0;
    // 依次将未放入S集合的结点中,取dist[]最小值的结点,放入结合S中
    // 一旦S包含了所有V中顶点,dist就记录了从源点到所有其他顶点之间的最短路径长度;
    for(i=0;i<n;i++)
    {
        min=INF;
        for(j=0;j<n;j++)
        {
            if(!mark[j]&&d[j]<min)
            {
                k=j;
                min=d[j];//找出未访问的点的最小的d[j]值;
            }
        }
        if(min==INF)
            break;
        mark[k]=1;//k已经放入了集合S;
        //更新距离,记录前驱;
        for(j=0;j<n;j++)
        {
            if(!mark[j]&&d[j]>d[k]+map[k][j])
            {
                d[j]=d[k]+map[k][j];
                pre[j]=k;
            }
        }
    }
    if(d[e]!=INF)
        cout<<d[e]<<endl;
    else
        cout<<-1<<endl;
}

inline void printpath(int pre[],int s,int e)//打印从s到e的路径;
{
    int path[maxn];
    int cnt=0;
    path[cnt]=e;
    cnt++;
    int cur=pre[e];

    while(cur!=s)
    {
        path[cnt]=cur;
        cnt++;
        cur=pre[cur];
    }
    path[cnt]=s;
    printf("%d-->",s);
    for(int i=cnt-1;i>=0;i--)
    i==0?printf("%d\n",path[i]):printf("%d-->",path[i]);
}

int main()
{
    int a,b,w,i,j;
    while(cin>>n>>m)
    {
        for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
            {
                map[i][j]=INF;
            }
        }
        for(i=0;i<m;i++)
        {
            cin>>a>>b>>w;
            map[a][b]=min(w,map[a][b]);
        }
        printf("输入起始点:\n");
        cin>>s>>e;
        printf("这是从%d到%d的最短距离\n",s,e);
        Dijkstra();
        printf("这是其经过的路径:");
        printpath(pre,s,e);
    }
    return 0;
}
/*
test cases:
6 8
0 2 100
0 5 10
1 5 5
5 4 50
0 3 30
3 2 60
3 4 20
4 2 10
0 2

output:60
0-->3-->4-->2
*/


 

toposort:

/*************************************************************************
* author:crazy_石头
* algorithm:toposort
* date:2013/10/20
* 程序功能:MST
* 算法流程:每一步总是输出当前无前趋(即人度为零)的顶点,其抽象算法可描述为:
         NonPreFirstTopSort(G)
             {//优先输出无前趋的顶点
             while(G中有人度为0的顶点)do
                 {
              从G中选择一个人度为0的顶点v且输出之;
              从G中删去v及其所有出边;
             }
             if(输出的顶点数目<|V(G)|)
                  //若此条件不成立,则表示所有顶点均已输出,排序成功。
              Error("G中存在有向环,排序失败!");
          }
**************************************************************************/
#include <iostream>
#include <cstring>
#include <cstdio>
#include <queue>
#include <algorithm>

using namespace std;

int map[505][505];
int indegree[505];
int main()
{
    int n,m;
    while(scanf("%d%d",&n,&m)!=EOF)
    {
        if(n==0&&m==0)
            break;
        int i,a,b;
        memset(map,0,sizeof(map));
        for(i=0;i<m;i++)
        {
            scanf("%d%d",&a,&b);
            map[a][b]=1;
        }

        memset(indegree,0,sizeof(indegree));
        int j;
        for(i=0;i<n;i++)
        {
            for(j=0;j<n;j++)
                if(map[i][j])
                    indegree[j]++;
        }
        priority_queue<int,vector<int>,greater<int> > q;
        for(i=0;i<n;i++)
            if(indegree[i]==0)
                q.push(i);
        int count=0;
        while(!q.empty())
        {
            int t=q.top();
            q.pop();
            printf("当前访问点为:%d\n",t);
            count++;
            for(i=0;i<n;i++)
            {
                if(map[t][i])
                {
                    indegree[i]--;
                    if(indegree[i]==0)
                        q.push(i);
                }
            }
        }
        if(count==n)
            printf("拓扑结果为:YES\n");
        else
            printf("拓扑结果为:NO\n");
    }
    return 0;
}
/*test:
6 8
0 2
0 5
0 3
1 5
5 4
4 2
3 2
3 4

output:0-->1-->3-->5-->4-->2
*/


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值