hdu 5545 The Battle of Guandu spfa最短路
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5545
题意:有N个村庄, M 个战场; $ 1 <=N,M <= 10^5 $;
其中曹操会从第i个村庄中选出若个人 在x[i]战场为其作战, 同时第i个村庄也会有相同的人数在y[i]战场为袁绍作战;
每个战场i 有对应的重要度w[i],w[i]的值为 0,1,2;
w[i]为2的战场,要求曹操的兵数(从村庄得到的) 严格大于 袁绍的兵的数量;
w[i]为1的战场,曹操的兵数不少于袁绍的兵即可;
w[i]为0的兵,没限制要求;
并且每个村庄派出一个兵有对应的花费c[i], 问要使得曹操在所有的战场士兵人数满足上面的要求,曹操至少花费为多少/
思路:
以贪心的思想很容易想到应该从重要程度为2的村庄开始考虑,如果村庄 i满足w[i]等于2,那么曹操先往该村庄派遣一个士兵;那么由题意知,在y[i]战场 袁绍的并多了1个;怎么办?
是不是曹操就需要往y[i]战场添加士兵呢?
不一定,需要看y[i]战场的重要程度,如果重要程度为0呢~~
所以只需要**递推**到重要程度为0的战场即可;
那怎么考虑花费最少呢?
以每个村庄的**价格**作为边的权值,求出所有w[i]为2的点到最近的w[j] = 0的最短路即可;
但如果直接建边,以重要度为2的战场作为源点spfa到重要度为0的重点,得到的将是曹操为重要度为0的战场的花费;所以反向建边,开始将W[i] = 0的放入队列即可;
spfa解法:
1 #pragma comment(linker, "/STACK:1024000000,1024000000") 2 #include<bits/stdc++.h> 3 using namespace std; 4 #define rep0(i,l,r) for(int i = (l);i < (r);i++) 5 #define rep1(i,l,r) for(int i = (l);i <= (r);i++) 6 #define rep_0(i,r,l) for(int i = (r);i > (l);i--) 7 #define rep_1(i,r,l) for(int i = (r);i >= (l);i--) 8 #define MS0(a) memset(a,0,sizeof(a)) 9 #define MS1(a) memset(a,-1,sizeof(a)) 10 #define MSi(a) memset(a,0x3f,sizeof(a)) 11 #define pb push_back 12 #define MK make_pair 13 #define A first 14 #define B second 15 #define clear0 (0xFFFFFFFE) 16 #define inf 0x3f3f3f3f 17 #define INF 0x3f3f3f3f3f3f3f3f 18 #define eps 1e-8 19 #define mod 1000000007 20 #define zero(x) (((x)>0?(x):-(x))<eps) 21 #define bitnum(a) __builtin_popcount(a) 22 #define lowbit(x) (x&(-x)) 23 #define K(x) ((x)*(x)) 24 #define debug(x) printf(" ---- %d\n",x) 25 typedef pair<int,int> PII; 26 typedef long long ll; 27 typedef unsigned int uint; 28 typedef unsigned long long ull; 29 template<typename T> 30 void read1(T &m) 31 { 32 T x = 0,f = 1;char ch = getchar(); 33 while(ch <'0' || ch >'9'){ if(ch == '-') f = -1;ch=getchar(); } 34 while(ch >= '0' && ch <= '9'){ x = x*10 + ch - '0';ch = getchar(); } 35 m = x*f; 36 } 37 template<typename T> 38 void read2(T &a,T &b){read1(a);read1(b);} 39 template<typename T> 40 void read3(T &a,T &b,T &c){read1(a);read1(b);read1(c);} 41 template<typename T> 42 void out(T a) 43 { 44 if(a>9) out(a/10); 45 putchar(a%10+'0'); 46 } 47 inline ll gcd(ll a,ll b){ return b == 0? a: gcd(b,a%b); } 48 inline ll lcm(ll a,ll b){ return a/gcd(a,b)*b; } 49 template<class T1, class T2> inline void gmax(T1& a, T2 b){ if(a < b) a = b;} 50 template<class T1, class T2> inline void gmin(T1& a, T2 b){ if(a > b) a = b;} 51 const int dx[] = {-1,0,1,0}, dy[] = {0,1,0,-1}; 52 const int maxn = 100007; 53 int head[maxn], tot; 54 ll dist[maxn], vs[maxn]; 55 void init(){ 56 MS0(head); 57 MSi(dist); 58 tot = 0; 59 } 60 struct edge{ 61 int to, w, nxt; 62 } e[maxn << 1]; 63 64 void ins(int u,int v,int w) 65 { 66 e[++tot].nxt = head[u]; 67 e[tot].to = v; 68 e[tot].w = w; 69 head[u] = tot; 70 } 71 int x[maxn], y[maxn], c[maxn], w[maxn]; 72 int que[maxn]; 73 ll build(int n, int m) 74 { 75 int h = 0, t = 0; 76 rep1(i,1,n){ 77 ins(y[i], x[i], c[i]); 78 if(w[y[i]] == 0 && dist[y[i]] == INF) 79 que[t++] = y[i], dist[y[i]] = 0; 80 } 81 while(h < t){ 82 int u = que[h++]; vs[u] = 0; 83 for(int id = head[u]; id; id = e[id].nxt){ 84 int v = e[id].to, w = e[id].w; 85 if(dist[v] > dist[u] + w){ 86 dist[v] = dist[u] + w; 87 if(vs[v] == 0){ 88 que[t++] = v; 89 vs[v] = 1; 90 } 91 } 92 } 93 } 94 ll ans = 0; 95 for(int i = 1; i <= m; i++) if(w[i] == 2){ 96 if(dist[i] == INF) return -1; 97 ans += dist[i]; 98 } 99 return ans; 100 } 101 int main() 102 { 103 //freopen("data.txt","r",stdin); 104 //freopen("out.txt","w",stdout); 105 int T, kase = 1; 106 scanf("%d",&T); 107 while(T--){ 108 init(); 109 int n, m; 110 read2(n, m); 111 rep1(i,1,n) read1(x[i]); 112 rep1(i,1,n) read1(y[i]); 113 rep1(i,1,n) read1(c[i]); 114 rep1(i,1,m) read1(w[i]); 115 printf("Case #%d: %I64d\n",kase++, build(n, m)); 116 } 117 return 0; 118 }