首页 > 其他 > 详细

[模拟赛FJOI Easy Round #2][T3 skill] (最小割+最大权闭合子图(文理分科模型))

时间:2017-01-08 19:18:01      阅读:292      评论:0      收藏:0      [点我收藏+]

【题目描述】

天上红绯在游戏中扮演敏剑,对于高攻击低防御的职业来说,爆发力显得非常重要,为此,她准备学习n个技能,每个技能都有2个学习方向:物理攻击和魔法攻击。对于第i个技能,如果选择物理攻击方向,会增加ap_i的爆发力,如果选择魔法攻击的方向,会增加ad_i的爆发力。此外,还有一些combo,一个combo由两个技能组成,对于第i个combo,如果他们都是魔法攻击,会额外增加AD_i的爆发力,如果他们都是物理攻击,会额外增加AP_i的爆发力,如果他们不属于同一类型,会减少AX_i的爆发力。她找到了你,请你帮她选择技能的类型,产生最大的爆发力。(说明:每个技能都必须学习)

【输入数据】

第一行2个正整数n,m,表示技能的个数和combo的个数

接下来n行每行2个正整数,描述一个技能的ap_i,ad_i

接下来m行每行5个正整数u,v,AD_i,AP_i,AX_i,描述一个combo,表示技能u和技能v产生combo

【输出数据】

一行,一个整数,表示最大的爆发力

【样例输入】

2 1
50 5
10 20
1 2 100 50 50

【样例输出】

125

【样例解释】

均选择魔法攻击,获得5+20+100=125的爆发力

【数据范围】

测试点编号

n

m

1

5

5

2

50

100

3

100000

0

4

500000

0

5-7

1000

3000

8-10

10000

40000

对于所有的测试点,确保不会爆long long

Solution

模型:最小割,最大权闭合子图

来自出题者的题解:可以先看作我们把所有的技能的收益(不包括亏损AX)都获得了,然后在这个获益中扣除最小的代价

建图:

对于每个技能,建边(S,u,ap),(u,T,ad)

对于每个combo,拆点,对点一建边(S,buf1,AD),(buf1,u,+∞),(buf1,v,+∞)

对点二建边(buf2,T,AP),(u,buf2,+∞),(v,buf2,+∞)

跑个最大流算法就行

#include<stdio.h>
#include<limits.h>
#include<string.h>
#define LL long long
#define dmin(a,b) ((a)<(b)?(a):(b))
inline int Rin(){
    int x=0,c=getchar(),f=1;
    for(;c<48||c>57;c=getchar())
        if(!(c^45))f=-1;
    for(;c>47&&c<58;c=getchar())
        x=(x<<1)+(x<<3)+c-48;
    return x*f;
}
const int N=500010;
const int M=40010;
const LL LINF=LONG_LONG_MAX/3*2;
LL tot(0);
int n,m,S,T,ecnt=1,fst[N+M*2];
struct edge{
    int u,v,nxt;
    LL cap,flow;
}e[(6*M+2*N)*2];
inline void link(int x,int y,LL w){
    e[++ecnt].u=x;e[ecnt].v=y;
    e[ecnt].cap=w;e[ecnt].flow=0;
    e[ecnt].nxt=fst[x];fst[x]=ecnt;
    e[++ecnt].u=y;e[ecnt].v=x;
    e[ecnt].cap=0;e[ecnt].flow=0;
    e[ecnt].nxt=fst[y];fst[y]=ecnt;
}
bool vis[N+M*2];
int num[N+M*2],cur[N+M*2],d[N+M*2],p[N+M*2],q[N+M*2];
void bfs(){
    int hd=0,tl=1;
    q[0]=T;d[T]=0;vis[T]=true;
    while(hd^tl){
        int now=q[hd++];
        for(int j=fst[now];j;j=e[j].nxt)
            if(!vis[e[j].u] && e[j].cap>e[j].flow)
                vis[e[j].u]=true,
                d[e[j].u]=d[now]+1,
                q[tl++]=e[j].u;
    }
}
inline LL Agument(){
    LL a=LINF;
    int x=T;
    while(x^S)
        a=dmin(a,e[p[x]].cap-e[p[x]].flow),
        x=e[p[x]].u;
    x=T;
    while(x^S)
        e[p[x]].flow+=a,
        e[p[x]^1].flow-=a,
        x=e[p[x]].u;
    return a;
}
LL ISAP(){
    int x(S);
    LL flow(0);
    bfs();
    for(int i=S;i<=T;i++)num[d[i]]++;
    for(int i=S;i<=T;i++)cur[i]=fst[i];
    while(d[S]<T){
        if(!(x^T))
            flow+=Agument(),
            x=S;
        bool advanced=false;
        for(int j=cur[x];j;j=e[j].nxt)
            if(e[j].cap>e[j].flow && d[x]==d[e[j].v]+1){
                advanced=true;
                cur[x]=j;
                p[e[j].v]=j;
                x=e[j].v;
                break;
            }
        if(!advanced){
            int mn=T-1;
            for(int j=fst[x];j;j=e[j].nxt)
                if(e[j].cap>e[j].flow)
                    mn=dmin(mn,d[e[j].v]);
            if(--num[d[x]]==0)break;
            num[d[x]=mn+1]++;
            cur[x]=fst[x];
            if(x^S)x=e[p[x]].u;
        }
    }
    return flow;
}
int main(){
    freopen("skill.in","r",stdin);
    freopen("skill.out","w",stdout);
    n=Rin(),m=Rin();
    S=1,T=n+1+m*2+1;
    for(int i=1;i<=n;i++){
        LL ap=Rin(),ad=Rin();
        tot+=ap+ad;
        link(S,i+1,ap);
        link(i+1,T,ad);
    }
    for(int i=1;i<=m;i++){
        int u=Rin(),v=Rin();
        LL AP=Rin(),AD=Rin(),AX=Rin();
        tot+=AP+AD;
        link(u+1,v+1,AX);
        link(v+1,u+1,AX);
        link(S,n+1+i,AD);
        link(n+1+i,u+1,LINF);
        link(n+1+i,v+1,LINF);
        link(n+1+i+m,T,AP);
        link(u+1,n+1+i+m,LINF);
        link(v+1,n+1+i+m,LINF);
    }
    printf("%I64d\n",tot-ISAP());
    fclose(stdin);
    fclose(stdout);
    return 0;
}

 

[模拟赛FJOI Easy Round #2][T3 skill] (最小割+最大权闭合子图(文理分科模型))

原文:http://www.cnblogs.com/keshuqi/p/6262443.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!