UVA 10537 The Toll! Revisited(最短路变形)

来源:互联网 发布:两小无猜网络剧是bl吗 编辑:程序博客网 时间:2024/05/14 21:07

从s到t,每次经过一个村庄要缴纳1个单位的货物,经过一个城镇时,每20个货物就要缴纳一个,求字典序最小的最少花费路径。

用最短路的思想来解。从终点跑最短路,对于边<u, v>的边权值,如果u是村庄,边权自然是1,当u是城镇时,边权是min{key | key - (key+19)/20=d[u]}。

求出最短路后,从起始点dfs,每次沿着满足最距离且字典序最小的边走就OK了~

#include<algorithm>#include<iostream>#include<cstring>#include<cstdlib>#include<fstream>#include<sstream>#include<string>#include<vector>#include<cstdio>#include<queue>#include<stack>#include<cmath>#include<map>#include<set>#define FF(i, a, b) for(int i=a; i<b; i++)#define FD(i, a, b) for(int i=a; i>=b; i--)#define REP(i, n) for(int i=0; i<n; i++)#define CLR(a, b) memset(a, b, sizeof(a))#define debug puts("**debug**")#define PB push_back#define LL long longusing namespace std;LL bin(LL k) //二分查找路过城镇前所需最少货物{    LL L=0, R=k*2+1, M, ans;    while(L <= R)    {        M = (L + R) >> 1;        LL tmp = M - (M + 19) / 20;        if(tmp > k) R = M - 1;        else if(tmp == k) ans = M, R = M - 1;        else L = M + 1;    }    return ans;}const int maxn = 111;const LL INF = 10000000000;int n, m, s, t;string name, ans;struct heap{    LL d;    int u;    bool operator<(const heap rhs) const    {        return d > rhs.d;    }};vector<int> G[maxn];bool done[maxn];LL d[maxn], P;map<char, int> id;inline void init(){    REP(i, maxn) G[i].clear();    n = 0; name.clear(); ans.clear(); id.clear();}int get(char c){    if(!id.count(c)) id[c] = n++, name.PB(c);    return id[c];}void dij(int s){    REP(i, n) d[i] = INF; d[s] = P;    priority_queue<heap> q; q.push((heap){0, s});    CLR(done, 0);    while(!q.empty())    {        heap x = q.top(); q.pop();        int nc = G[x.u].size(), u = x.u;        if(done[u]) continue;        done[u] = 1;        REP(i, nc)        {            int v = G[u][i];            LL tmp = d[u] + 1;            if(isupper(name[u])) tmp = bin(d[u]);//边权            if(d[v] > tmp)            {                d[v] = tmp;                q.push((heap){d[v], v});            }        }    }}void dfs(int u){    if(u == t) return ;    char c = 'z';    int nc = G[u].size();    REP(i, nc)    {        int v = G[u][i];        LL tmp = d[u] - 1;        if(isupper(name[v])) tmp = d[u] - (d[u] + 19) / 20;        if(d[v] == tmp) if(name[v] <= c) c = name[v]; //走字典序最小的路径    }    ans.PB(c);    dfs(id[c]);}int main(){    int kase = 1;    while(scanf("%d", &m), m != -1)    {        init();        char a[2], b[2];        while(m--)        {            scanf("%s%s", a, b);            int aa = get(a[0]), bb = get(b[0]);            G[aa].PB(bb), G[bb].PB(aa);        }        scanf("%lld %s%s", &P, a, b);        s = get(a[0]), t = get(b[0]);        dij(t);        ans.PB(a[0]);        dfs(s);        printf("Case %d:\n", kase++);        printf("%lld\n", d[s]);        int nc = ans.size();        REP(i, nc) printf("%c%c", ans[i], i == nc-1 ? '\n' : '-');    }    return 0;}



原创粉丝点击