UVA 10246 Asterix and Obelix

题意:每个城市举办庆祝有一定的花费,A在路径上会选择庆祝花费最大的城市      

   让你求,A回家所花的路费和庆祝费最少,也就是说并不是最短路径就是结果,      

   还有可能就是路费比最短路径的多,但是庆祝费就比它的少,总的加起来可能更小。

思路:枚举每个城市作为庆祝的点,设为x。以x为源点,用dijks求单源路径,路径上如果有大于x庆祝费的点,则不考虑进去。      

    求完所有点到x的单源路径后,用两重j、k的for循环,同步更新从j到k所需要的最小花费

 

 

#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <cstring>
#include <stdio.h>
#include <map>
#include <vector>
using namespace std;
const int maxn=0x3f3f3f3f;

int c,r,q;
int c1,c2,d;
int a,b;
int road[101][101];
int feast[101];
int ans[81][81];//ans[i][j]即为询问的答案,表示i到j最少的花费
int dis[81];//当x为庆祝点时,dis[i]表示以第x城市作为举办宴会的地方,i到x之间的最短路径(即花费);
vector<int> link[101];
int vis[81];
int cases=0;
int blank=0;

void init(){
    for(int i=0;i<=c;i++)
        link[i].clear();
    memset(road,maxn,sizeof(road));
    memset(ans,maxn,sizeof(ans));
}
int main()
{
    while(scanf("%d%d%d",&c,&r,&q)!=EOF){
        if(c==0 && r==0 && q==0)
            break;
        //如果不这样,则最后一个case输出完后会多打一个空格,这也给我wrong answer。。。
        if(blank)
            puts("");
        else
            blank=1;
        cases++;
        init();
        for(int i=1;i<=c;i++){
            scanf("%d",&feast[i]);
        }
        for(int i=0;i<r;i++){
            scanf("%d%d%d",&c1,&c2,&d);
            road[c1][c2]=d;
            road[c2][c1]=d;
            link[c1].push_back(c2);
            link[c2].push_back(c1);
        }

        for(int i=1;i<=c;i++){

            //以i作为庆祝城市,并且以i作为源点,求单源路径
            memset(dis,maxn,sizeof(dis));
            dis[i]=0;
            memset(vis,0,sizeof(vis));

            //循环n次,这里我没用优先级队列
            for(int z=1;z<=c;z++){
                int mincost=maxn;
                int idx;
                for(int k=1;k<=c;k++){
                    if(vis[k]==0){
                        if(dis[k]<mincost && feast[k]<=feast[i]){
                            mincost=dis[k];
                            idx=k;
                        }
                    }
                }
                vis[idx]=1;
                for(int g=0;g<link[idx].size();g++){
                    int v=link[idx][g];
                    if(v!=idx){
                        if(feast[v]<=feast[i] && dis[idx]+road[idx][v]<dis[v]){
                            dis[v]=dis[idx]+road[idx][v];
                        }
                    }
                }
            }
           
           //每次求完以i为庆祝点的单源路径后,与之前比较,更新ans[j][k]的值,
        //如果此次,从j到k之间在i点庆祝的花费比之前一次循环中的在i'庆祝的花费要少,则更新
            for(int j=1;j<=c;j++){
                for(int k=1;k<=c;k++){
                    if(feast[i]+dis[j]+dis[k]<ans[j][k]){
                        ans[j][k]=feast[i]+dis[j]+dis[k];
                    }
                }
            }

        }
        printf("Case #%d\n",cases);
        for(int i=1;i<=q;i++){
            scanf("%d%d",&a,&b);
            if(ans[a][b]==maxn){
                printf("-1\n");
            }
            else{
                printf("%d\n",ans[a][b]);
            }
        }
        //printf("\n");

    }
    return 0;
}

 

posted @ 2013-08-25 11:10  辰曦~文若  阅读(335)  评论(0编辑  收藏  举报