topcoder SRM 642 解题报告

div2 1000pts

题意:

有一张图, N N 个节点(N50),每条边有一个高度值,The King要从某条路走过必须满足他的shoes高度小于等于这条路的高度值。他现在有一些金币,把一条边的高度约束上调 k k 个单位需要k2的金币,每条边只能上调一次。现在他要从 0 0 走到N1,求他能穿的最高shoes高度。

思路:

看起来像一个最短路吧,但是没有确切的边权,很难转移状态。
于是我想到先二分鞋子高度,在check的时候跑一遍最短路,这时边权是确定的,就很容易做最短路了。

1000pts里面比较基础的题。

贴代码:

#define ll long long
using namespace std;
const ll N = 50;
ll n, m, c, maxht;
vector<ll> to[N];
vector<ll> ht[N];
ll l, r, mid, ans;
ll dis[N];
bool inq[N];
queue<ll> q;

bool SPFA(ll std_ht, ll max_cost)
{
    while (!q.empty()) q.pop();
    memset(dis, -1, sizeof(dis));
    memset(inq, 0, sizeof(inq));
    q.push(0); inq[0] = 1; dis[0] = 0;
    while (!q.empty()){
        ll u = q.front();
        q.pop();
        inq[u] = 0;
        for (ll i = 0; i < to[u].size(); i++){
            ll v = to[u][i];
            ll cost = max(0ll, std_ht-ht[u][i]);
            cost *= cost;
            if (dis[v] == -1 || dis[v] > dis[u]+cost){
                dis[v] = dis[u]+cost;
                if (!inq[v] && dis[v] <= max_cost){
                    inq[v] = 1;
                    q.push(v);
                }
            }
        }
    }
    if (dis[n-1] == -1) return 0;
    else return (dis[n-1] <= max_cost);
}

class TallShoes {
public:
    int maxHeight( int N, vector <int> X, vector <int> Y, vector <int> height, long long B );
};
int TallShoes::maxHeight(int N, vector <int> X, vector <int> Y, vector <int> height, long long B) {
    //initialize
    n = N; m = X.size(); c = B;
    maxht = 0;
    for (ll i = 0; i < n; i++)
        to[i].clear(), ht[i].clear();
    for (ll i = 0; i < m; i++){
        to[X[i]].push_back(Y[i]);
        ht[X[i]].push_back(height[i]);
        to[Y[i]].push_back(X[i]);
        ht[Y[i]].push_back(height[i]);
        maxht = max(maxht, (ll)height[i]);
    }
    //main
    l = 0; r = maxht+sqrt(c);
    while (l <= r){
        mid = (l+r)>>1;
        if (SPFA(mid, c))
            ans = mid, l = mid+1;
        else r = mid-1;
    }
    return ans;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值