LG2045 方格取数加强版 费用流

问题描述

LG2045


题解

费用流。

套路拆点,把\((i,j)\)拆为两个点,在这两个点之间连边:一条边流量为\(1\),费用为\(a_{i,j}\),另一条边为流量为\(INF\),费用为\(0\)(表示联通)。

然后在\((i,j)\)的出点向\((i+1,j)\)\((i,j+1)\)连边,流量\(INF\),费用\(0\),表示联通。

建立\(S,T\),分别于\((1,1),(n,n)\)相连,流量为\(k\),费用为\(0\),代表可以走\(k\)次。

跑费用最大流即可。

传纸条本质是本题的特殊情况,即\(k=2\)的情况


\(\mathrm{Code}\)

#include<bits/stdc++.h>
using namespace std;

template <typename Tp>
void read(Tp &x){
    x=0;char ch=1;int fh;
    while(ch!='-'&&(ch>'9'||ch<'0')) ch=getchar();
    if(ch=='-') ch=getchar(),fh=-1;
    else fh=1;
    while(ch>='0'&&ch<='9') x=(x<<1)+(x<<3)+ch-'0',ch=getchar();
    x*=fh;
}

const int maxn=53;
const int maxm=1000000;
const int INF=0x3f3f3f3f;

int a[maxn][maxn],n,k;

int Head[maxn*maxn*2],S,T;
int Next[maxm],to[maxm],tot=1,w[maxm],cost[maxm];

void add(int x,int y,int z,int c){
    to[++tot]=y,Next[tot]=Head[x],Head[x]=tot,w[tot]=z,cost[tot]=c;
}

int calc(int x,int y,int t){
    return (x-1)*n+y+(t-1)*n*n;
}

bool vis[maxm];
int dis[maxm],pre[maxm],now[maxm];
bool spfa(){
    memset(vis,0,sizeof(vis));memset(dis,0xcf,sizeof(dis));
    memset(pre,0,sizeof(pre));
    queue<int>q;q.push(S);vis[S]=1,dis[S]=0;
    now[S]=INF;
    while(!q.empty()){
        int x=q.front();q.pop();
        vis[x]=0;
        for(int i=Head[x];i;i=Next[i]){
            int y=to[i],len=w[i],ct=cost[i];
            if(!len||dis[y]>=dis[x]+ct) continue;
            dis[y]=dis[x]+ct;now[y]=min(now[x],len);
            pre[y]=i;
            if(!vis[y]) q.push(y),vis[y]=1;
        }
    }
    return dis[T]!=0xcfcfcfcf;
}

int mx,ans;

void upd(){
    mx+=now[T],ans+=dis[T]*now[T];
    int p=T;
    while(p!=S){
        int k=pre[p];
        w[k]-=now[T],w[k xor 1]+=now[T];
        p=to[k xor 1];
    }
}

int main(){
    read(n);read(k);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            read(a[i][j]);
        }
    }
    S=n*n*2+1,T=S+1;
    add(S,calc(1,1,1),k,0);add(calc(1,1,1),S,0,0);
    add(calc(n,n,2),T,k,0);add(T,calc(n,n,2),0,0);
    for(int i=1;i<=n;i++){
        for(int j=1;j<=n;j++){
            add(calc(i,j,1),calc(i,j,2),1,a[i][j]);add(calc(i,j,2),calc(i,j,1),0,-a[i][j]);
            add(calc(i,j,1),calc(i,j,2),INF,0);add(calc(i,j,2),calc(i,j,1),0,0);
            if(i!=n) add(calc(i,j,2),calc(i+1,j,1),INF,0),add(calc(i+1,j,1),calc(i,j,2),0,0);
            if(j!=n) add(calc(i,j,2),calc(i,j+1,1),INF,0),add(calc(i,j+1,1),calc(i,j,2),0,0);
        }
    }
    while(spfa())
        upd();
    printf("%d\n",ans);
    return 0;
}
全部评论

相关推荐

03-14 10:50
已编辑
门头沟学院 Java
鼠鼠华子无线实习,bg双九,通软岗位,论文,专利,竞赛都水过一点,秋招《非all&nbsp;in》选手,《泡池子泡到肿》选手,分享一下自己的时间线,给大家多一个参考。---实习末期,接口人电话沟通,最终决定求稳继续投递实习原部门---免机试,九月走完线下流程,开始入池---十月起开始保温,打听手中已拿offer,比较薪资,给出华子的预估职级和薪资(完全不给A的空间)---十月第二次保温,询问签约情况,各种暗示劝说留空白三方---十月底签约另一家公司,遂被降低优先级---十一月若干次常规保温信息(还有机会/稍晚一点/等这周。。。)---十二月告知部门有13的指标,愿意接受可以立刻发offer(难绷,妄图性...
蓦然回首一枝花:能体会楼主的心情,我投了华为无线的成研所,双9bg,被华子最后开了个13级的侮辱价 12.3打oc电话的时候接口人表示乐观等待就行,然后中间4周就开始不回消息或者拖四五天才回,翻来覆去就是“等审批结果”。 12月27号,我看应该是泡不出来了所以联系了部门流转,这时候接口人开始主动给我打电话告诉我马上就能出结果了,于是我也没继续流转。 12.31给我打电话说得降薪审批,薪资大概就是对应着13级的样子,但我当时因为投的是成都的,没有意识到薪资是按照上海开的,还以为这个薪资在成都是14级,加上那个时候我也“孝”劲上来了,想着能收我就行,于是答应了。 1.13开了出来,联系我了薪资,确认了下发现是13级,当时实在是接受不了,于是最终还是拒了。 拒的时候接口人告诉我说这个hc真的是他们争取了很久才争取到的,不过我一想到我12.3就打了oc电话,中间4周一直不搭理我或吊着我,最后12.31才告诉我争取不下来14级要降薪,也许争取真的要争取那么久吧,呵。 这个过程中也为华为拒了不少offer,大厂的、央企的、银行的都拒过,网上总说“华为没有发小奖状之前hr的话一个字都不要信”,当时没有放在心上,以为不会摊到我头上,现在来看当时也挺年轻气盛的。我感觉要不是中途我一直在烦hr,可能我就和楼主一样被泡死了吧,不过最后给开了个13级也和泡死没差,不过是被多侮辱了一次。 最后借楼主这个贴就只想跟后面的人提一个建议吧,还是那句说烂了的,“华为没有发小奖状之前hr的话一个字都不要信”,真的不要以为这样的情况不会出现在自己身上,不要拿自己的一辈子前途去送华为hr业绩。
点赞 评论 收藏
分享
1个小白:可以考虑投一下字节
点赞 评论 收藏
分享
Aaso:挺好的,早挂早超生
点赞 评论 收藏
分享
评论
点赞
收藏
分享

创作者周榜

更多
牛客网
牛客企业服务