昂贵的聘礼(poj1062)dijkstra

#include <stdio.h>
int main()
{
    //distance[i]表示i到已经到达的点的最小距离,origin[101][101]是图的邻接矩阵存储,M是等级限制,n为物品总数,图中共有n+1个点,rank[i]为第i个主人的等级
    int M,n,i,j,k,jcost,origin_max=0,distance[101],min_cost,origin[101][101],rank[101],temp,last_rank,vertex,min_distance;
    //flag[i]存放第i个节点是否已经到达
    bool flag[101];
    scanf("%d %d",&M,&n);
    //邻接矩阵初始化
    for(i=0;i<=n;i++)
        for(j=0;j<=n;j++)
            origin[i][j]=-1;
    //对每个物品初始化
    for(i=1;i<=n;i++)
    {
        scanf("%d %d %d",&origin[0][i],&rank[i],&temp);
 //对每一个替代品,初始化origin
        for(k=0;k<temp;k++)
        {
            scanf("%d %d",&j,&jcost);
            origin[j][i]=jcost;
        }
    }
    //取邻接矩阵中的最大值origin_max
    for(i=0;i<=n;i++)
        for(j=0;j<=n;j++)
            if(origin[i][j]>origin_max)
                origin_max=origin[i][j];
     //如果没有值就设为origin_max+1,这样不会对结果有影响
     for(i=0;i<=n;i++)
        for(j=0;j<=n;j++)
            if(origin[i][j]==-1)
                origin[i][j]=origin_max+1;
    min_cost=origin_max+1;
    //last_rank表示酋长的rank
    last_rank=rank[1];
    //假如酋长的rank(last_rank)=10,等级限制M=5,那么可以参与交易的等级有以下6种可能:5-10 6-11 7-12 8-13 9-14 10-15
    //下面这个循环就是分别处理这M+1种可能
    for(i=0;i<=M;i++)
    {
 //这M+1种可能是独立的,一定不能相互影响,然后取最小值,所以要在副本上(copy[][])进行操作
 //开始一直wa就是这里出了问题,找了很长时间
        int copy[101][101];
        for(j=0;j<=n;j++)
            for(k=0;k<=n;k++)
                copy[j][k]=origin[j][k];
 //对每一个主人(除了酋长)的rank检查是否在要求的rank范围内,如果不在就将其代价设为最大值(origin_max+1)
        for(j=2;j<=n;j++)
        {
            if(rank[j]<last_rank-M+i||rank[j]>last_rank+i)
                for(k=0;k<=n;k++)
                {
                    copy[j][k]=origin_max+1;
                }
        }
 //下面是Dijkstra算法,和prim算法极为相似
 //将flag设为false,除了flag[0]
        for(j=0;j<=n;j++)
        {
            flag[j]=false;
            distance[j]=copy[0][j];
        }
        flag[0]=true;
 //循环直到终点出现在可到达的距离中
        while(true)
        {
            min_distance=origin_max+1;
            for(j=1;j<=n;j++)
            {
  //找到最小距离加入到集合中
                if(!flag[j]&&distance[j]<min_distance)
                {
                    vertex=j;
                    min_distance=distance[j];
                }
            }
     //如果加入的是终点,即酋长
            if(vertex==1)
            {
  //发现更小的距离
                if(min_cost>min_distance)
                    min_cost=min_distance;
                break;
            }
            flag[vertex]=true;
     //更新最小距离
            for(j=1;j<=n;j++)
            {
                if(!flag[j])
                    distance[j]=distance[j]<copy[vertex][j]+distance[vertex]?distance[j]:copy[vertex][j]+distance[vertex];
            }
        }
    }
    printf("%d\n",min_cost);
    return 1;
}
posted @ 2011-03-05 21:47  acm_poj  阅读(304)  评论(0)    收藏  举报