【USACO 2.4 】Bessie Come Home

题意:给出n条有权的双向边(10000),求到达Z最近的大写字母,及其距离。

题解:即求Z出发的最短路,用dijstra就可以了,注意边要开到20000以上。

/*
TASK: comehome
LANG:C++
*/
#include<cstdio>
#include<algorithm>
#include<cstring>
#include<queue>

#define N 52
#define M 20005
#define inf 0x3f3f3f3f

using namespace std;

struct edge{
    int next,to,w;
}e[M];
int head[N],cnt;

void add(int u,int v,int w){
    e[++cnt]=(edge){head[u],v,w};head[u]=cnt;
    e[++cnt]=(edge){head[v],u,w};head[v]=cnt;
}
int get(char c){
    if(c<'a')return c-'A'+26;
    return c-'a';
}

int dis[N],b[N];
struct cmp{
    bool operator ()(int a,int b){
        return dis[a]>dis[b];
    }
};
priority_queue<int,vector<int>,cmp>q;
void dijkstra(){
    int s=get('Z');
    int ans=inf,ansi;
    memset(dis,inf,sizeof dis);
    dis[s]=0;
    q.push(s);
    while(!q.empty()){
        int p=q.top();
        q.pop();
        if(b[p])continue;
        b[p]=1;//出队列时标记它已经用来更新过。
        for(int i=head[p];i;i=e[i].next){
            int v=e[i].to;
            if(!b[v]&&dis[v]>dis[p]+e[i].w){
                dis[v]=dis[p]+e[i].w;
                if(v<51&&v>25&&dis[v]<ans){
                    ans=dis[v];
                    ansi=v;
                }
                q.push(v);
            }
        }
    }
    printf("%c %d\n",ansi+'A'-26,ans);
}
int main(){
    freopen("comehome.in","r",stdin);
    freopen("comehome.out","w",stdout);
    char u,v;
    int n,w;
    scanf("%d",&n);
    for(int i=1;i<=n;i++){
        scanf(" %c %c %d",&u,&v,&w);
        if(u!=v) add(get(u),get(v),w);
    }
    dijkstra();
    return 0;
}
View Code

 

  

posted @ 2016-11-15 11:33  水郁  阅读(429)  评论(0编辑  收藏  举报
……