zoukankan      html  css  js  c++  java
  • P2045 方格取数加强版

    P2045 方格取数加强版


    傻逼题。

    每个点拆成入点a和出点b,S向a(1,1)连边,b(n,n)向T连边。流量为k,费用为0.

    由于点只能去一次,所以a(i,j)向b(i,j)连一条1流量-A[i][j]费用的边,再连一条k-1流量0费用的边。

    再就是每个出点都向相邻入点连一条流量k费用0的边。

    // It is made by XZZ
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #define il inline
    #define rg register
    #define vd void
    #define sta static
    typedef long long ll;
    il int gi(){
        rg int x=0,f=1;rg char ch=getchar();
        while(ch<'0'||ch>'9')f=ch=='-'?-1:f,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*f;
    }
    const int maxn=50*50*2+10,maxm=1e7,S=maxn-2,T=maxn-1;
    int num[51][51];
    int fir[maxn],dis[maxm],nxt[maxm],w[maxm],cost[maxm],id=1;
    il vd link(int a,int b,int c,int d){
        nxt[++id]=fir[a],fir[a]=id,dis[id]=b,w[id]=c,cost[id]=d;
        nxt[++id]=fir[b],fir[b]=id,dis[id]=a,w[id]=0,cost[id]=-d;
    }
    il bool SPFA(int&Cost){
        sta int que[10000000],hd,tl,lst[maxn],dist[maxn];
        sta bool inque[maxn]={0};
        memset(dist,63,sizeof dist);
        dist[S]=0;
        hd=tl=0;que[tl++]=S;inque[S]=1;
        while(hd^tl){
            int x=que[hd];
            for(rg int i=fir[x];i;i=nxt[i]){
                if(w[i]&&dist[dis[i]]>dist[x]+cost[i]){
                    dist[dis[i]]=dist[x]+cost[i];lst[dis[i]]=i;
                    if(!inque[dis[i]])inque[dis[i]]=1,que[tl++]=dis[i];
                }
            }
            inque[x]=0;++hd;
        }
        if(dist[T]==dist[0])return 0;
        int flow=1e9;
        for(rg int i=lst[T];i;i=lst[dis[i^1]])flow=std::min(flow,w[i]);
        for(rg int i=lst[T];i;i=lst[dis[i^1]])w[i]-=flow,w[i^1]+=flow,Cost+=flow*cost[i];
        return 1;
    }
    il vd Mincost(int&cst){cst=0;while(SPFA(cst));}
    int main(){
    #ifdef xzz
        freopen("2045.in","r",stdin);
        freopen("2045.out","w",stdout);
    #endif
        int n=gi(),k=gi();
        for(rg int i=1;i<=n;++i)
            for(rg int j=1;j<=n;++j)
                num[i][j]=++num[0][0],++num[0][0];
        for(rg int i=1;i<=n;++i)
            for(rg int j=1;j<=n;++j)
                link(num[i][j],num[i][j]+1,1,-gi()),link(num[i][j],num[i][j]+1,k-1,0);
        link(S,num[1][1],k,0);
        link(num[n][n]+1,T,k,0);
        for(rg int i=1;i<=n;++i)
            for(rg int j=1;j<n;++j)
                link(num[i][j]+1,num[i][j+1],k,0);
        for(rg int i=1;i<n;++i)
            for(rg int j=1;j<=n;++j)
                link(num[i][j]+1,num[i+1][j],k,0);
        int Cost;Mincost(Cost);
        printf("%d
    ",-Cost);
        return 0;
    }
    
  • 相关阅读:
    PosegreSQL基础回顾(第 5 章 数据定义)
    PosegreSQL基础回顾(第 4 章 SQL语法)
    大数据学习2(伪分布式搭建)
    大数据学习2(MapReduce)
    大数据学习1(HDFS)
    Linux find用法
    shell循环
    查询一次数据库给多个变量赋值
    linux cut用法
    linux权限
  • 原文地址:https://www.cnblogs.com/xzz_233/p/8718873.html
Copyright © 2011-2022 走看看