div2 1000pts
题意:
有一张图, N N 个节点,每条边有一个高度值,The King要从某条路走过必须满足他的shoes高度小于等于这条路的高度值。他现在有一些金币,把一条边的高度约束上调 k k 个单位需要的金币,每条边只能上调一次。现在他要从 0 0 走到,求他能穿的最高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;
}