HDU 5545 The Battle of Guandu(最短路)

来源:互联网 发布:知乎 修改一句话介绍 编辑:程序博客网 时间:2024/06/07 00:00

哇一开始看错了x[i]的意思,看了许久题解也没理解。

一开始明白一点,就是lv2的战场上曹操只需要比袁绍多一个人即可,lv0的战场曹操肯定是不花钱去买士兵的,lv1的战场就让他相等着吧,多了也没意义。

然后我们可以先假设,如果这道题只是问曹操是否可以战胜袁绍,输出yes或者no的话,条件就是,有一个村庄往一个lv0的战场参加袁绍的军队,并且往一个lv2的战场参加曹操的军队,又或者能构成一个村庄去lv0参加袁绍,去lv1参加曹操,并且有一个村庄参加这个lv1的战场的袁绍军队,然后去一个lv2的战场参加曹操军队。但是现在是要问是否可以战胜,最小花费是多少。

按照上面的思路,其实x[i]和y[i]是固定的,所以说白了就是去了y[i]就可以往x[i]派士兵,花费为c[i],那不如直接把y[i]连一条有向边去x[i],并且花费为c[i]。这样一个有向图建好之后,我们着重看的lv2的战场,这个战场曹操比袁绍多的一个士兵到底是从哪里来的?还不是从lv0来的,上面那段也说明了lv0肯定是起点。所以我们跑一个多源最短路即可。然后统计一下lv2的战场。有的lv2的战场可能没有lv0的战场能到达,那么就说明曹操是无法战胜袁绍的,输出-1即可。

代码如下:

#include<iostream>#include<cstdio>#include<vector>#include<queue>#include<utility>#include<stack>#include<algorithm>#include<cstring>#include<string>#include<cmath>#include<set>#include<map>using namespace std;typedef long long ll;typedef pair<ll, int> pii;const int maxn = 1e5 + 5;const ll INF = 1e18;int n, m;vector <pii> edge[maxn];ll dis[maxn];int x[maxn], y[maxn], w[maxn];ll c[maxn];priority_queue <pii, vector<pii>, greater<pii> > q;ll dijkstra() {while(!q.empty()) {pii tmp = q.top();q.pop();int u = tmp.second;if(dis[u] < tmp.first)continue;for(int i = 0; i < edge[u].size(); i++) {ll d = edge[u][i].first + dis[u];int v = edge[u][i].second;if(dis[v] > d) {dis[v] = d;q.push(pii(dis[v], v));}}}ll ans = 0;for(int i = 1; i <= m; i++) {if(w[i] == 2) {if(dis[i] != INF) {ans += dis[i];} else {return -1;}}}return ans;} int main() {#ifndef ONLINE_JUDGEfreopen("in.txt", "r", stdin);//    freopen("out.txt", "w", stdout);#endifint T, Case = 1;scanf("%d", &T);while(T--) {scanf("%d%d", &n, &m);for(int i = 1; i <= n; i++) {scanf("%d", &x[i]);}for(int i = 1; i <= n; i++) {scanf("%d", &y[i]);}for(int i = 1; i <= n; i++) {scanf("%lld", &c[i]);}for(int i = 1; i <= m; i++) {scanf("%d", &w[i]);}fill(dis + 1, dis + m + 1, INF); for(int i = 1; i <= n; i++) {edge[y[i]].push_back(pii(c[i], x[i]));if(w[y[i]] == 0 && dis[y[i]] == INF) {dis[y[i]] = 0;q.push(pii(dis[y[i]], y[i]));}}ll ans = dijkstra();printf("Case #%d: %lld\n", Case++, ans);for(int i = 1; i <= n; i++) edge[i].clear();}return 0;}


阅读全文
0 0
原创粉丝点击