hdu5545The Battle of Guandu

来源:互联网 发布:百度网盘显示网络异常 编辑:程序博客网 时间:2024/06/06 23:53

链接:http://acm.hdu.edu.cn/showproblem.php?pid=5545

题意:有n个村庄和m个战场,从第i个村庄花费ci能让一个人去曹操的xi战场,一个人去袁绍的yi战场,对于每个战场有一个战略意义wi(0/1/2),为0的话输赢无所谓,为1的话不能输,为2必须赢,求最小花费使得曹操能赢整个大局,无解输出-1。

分析:对于每一个wi=2的战场因为贪心的话曹操的人一定恰好比袁绍对1人,wi=1的战场恰好相等初始是0=0,那么我们要使得wi=2的曹操战场多一人就得从能到这个战场的村庄借一人同时这个村庄会给对应的袁绍战场一个人,那么就是等价的从对应的另外一个曹操战场借一人。那么这个被借的最终一定要是wi=0的战场,那么我们就能建成一个多源(wi=0的战场)多汇(wi=2的战场)的最短路使得所有的wi=2的战场都能借来一人。跑个最短路即可。O(nlogn)

代码:

#include<map>#include<set>#include<cmath>#include<queue>#include<bitset>#include<math.h>#include<vector>#include<string>#include<stdio.h>#include<cstring>#include<iostream>#include<algorithm>#pragma comment(linker, "/STACK:102400000,102400000")using namespace std;const int N=100010;const int mod=100000000;const int MOD1=1000000007;const int MOD2=1000000009;const double EPS=0.00000001;typedef long long ll;const ll MOD=1000000007;const int INF=1000000010;const ll MAX=1ll<<55;const double pi=acos(-1.0);typedef double db;typedef unsigned long long ull;struct node {    int x;ll l;    node(){}    node(int x,ll l):x(x),l(l) {}    bool operator < (const node a) const { return l>a.l; }};int tot,u[N],v[N],p[N],pre[N];int n,m,q[N],x[N],y[N],c[N],w[N];void add(int a,int b,int c) {    v[tot]=b;p[tot]=c;pre[tot]=u[a];u[a]=tot++;}ll dis[N];priority_queue<node>Q;ll getmin() {    node now;    ll ret=0;memset(q,0,sizeof(q));    for (int i=1;i<=m;i++) dis[i]=MAX;    for (int i=1;i<=m;i++)    if (w[i]==0) dis[i]=0,Q.push(node(i,0));    while (!Q.empty()) {        now=Q.top();Q.pop();        if (q[now.x]) continue ;q[now.x]=1;        for (int i=u[now.x];i!=-1;i=pre[i])        if (dis[v[i]]>now.l+p[i]) {            dis[v[i]]=now.l+p[i];Q.push(node(v[i],dis[v[i]]));        }    }    for (int i=1;i<=m;i++)    if (w[i]==2&&dis[i]==MAX) return -1;    else if (w[i]==2) ret+=dis[i];    return ret;}int main(){    int i,t,ca;    scanf("%d", &t);    for (ca=1;ca<=t;ca++) {        scanf("%d%d", &n, &m);        for (i=1;i<=n;i++) scanf("%d", &x[i]);        for (i=1;i<=n;i++) scanf("%d", &y[i]);        for (i=1;i<=n;i++) scanf("%d", &c[i]);        for (i=1;i<=m;i++) scanf("%d", &w[i]);        tot=0;memset(u,-1,sizeof(u));        for (i=1;i<=n;i++) add(y[i],x[i],c[i]);        printf("Case #%d: %I64d\n", ca, getmin());    }    return 0;}


0 0
原创粉丝点击