• 【Luogu】P2045方格取数加强版(最小费用最大流)


      题目链接

      通过这题我学会了引诱算法的行为,就是你通过适当的状态设计,引诱算法按照你想要它做的去行动,进而达到解题的目的。

      最小费用最大流,首先将点拆点,入点和出点连一条费用=-权值,容量=1的边,再连费用=0,容量=INF的边,跑最小费用最大流即可。

      

    #include<cstdio>
    #include<cctype>
    #include<algorithm>
    #include<cstring>
    #include<cstdlib>
    #include<queue>
    #define maxn 10000
    #define maxm 500000
    using namespace std;
    
    inline long long read(){
        long long num=0,f=1;
        char ch=getchar();
        while(!isdigit(ch)){
            if(ch=='-')    f=-1;
            ch=getchar();
        }
        while(isdigit(ch)){
            num=num*10+ch-'0';
            ch=getchar();
        }
        return num*f;
    }
    
    int count(int i){    return i&1?i+1:i-1;    }
    int calc(int i,int j,int n){    return (i-1)*n+j;    }
    
    struct Edge{
        int from,next,to,val,flow,dis;
    }edge[maxm];
    int head[maxn],num;
    inline void addedge(int from,int to,int val,int dis){
        edge[++num]=(Edge){from,head[from],to,val,0,dis};
        head[from]=num;
    }
    inline void add(int from,int to,int val,int dis){
        addedge(from,to,val,dis);
        addedge(to,from,0,-dis);
    }
    
    bool vis[maxn];
    int dst[maxn];
    int flow[maxn];
    int pre[maxn];
    int Start,End;
    
    int spfa(){
        memset(vis,0,sizeof(vis));
        memset(dst,127/3,sizeof(dst));
        queue<int>q;    q.push(Start);    dst[Start]=0;    flow[Start]=0x7fffffff;
        while(!q.empty()){
            int from=q.front();    q.pop();    vis[from]=0;
            for(int i=head[from];i;i=edge[i].next){
                int to=edge[i].to;
                if(dst[to]<=dst[from]+edge[i].dis||edge[i].val<=edge[i].flow)    continue;
                pre[to]=i;
                dst[to]=dst[from]+edge[i].dis;
                //printf("%d %d %d
    ",from,to,dst[to]);
                flow[to]=min(flow[from],edge[i].val-edge[i].flow);
                if(vis[to])    continue;
                vis[to]=1;    q.push(to);
            }
        }
        if(dst[End]==dst[End+1])    return 0;
        int now=End;
        while(now!=Start){
            int ret=pre[now];
            edge[ret].flow+=flow[End];    edge[count(ret)].flow-=flow[End];
            now=edge[ret].from;
        }
        return dst[End];
    }
    
    int q[maxn][maxn];
    
    int main(){
        int n=read(),k=read();    End=maxn-10;
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j){
                q[i][j]=read();
                add(calc(i,j,n),calc(i,j,n)+n*n,1,-q[i][j]);
                add(calc(i,j,n),calc(i,j,n)+n*n,0x7fffffff,0);
            }
        for(int i=1;i<=n;++i)
            for(int j=1;j<=n;++j){
                if(i^n)    add(calc(i,j,n)+n*n,calc(i+1,j,n),0x7fffffff,0);
                if(j^n)    add(calc(i,j,n)+n*n,calc(i,j+1,n),0x7fffffff,0);
            }
        add(Start,calc(1,1,n),0x7fffffff,0);
        add(calc(n,n,n)+n*n,End,0x7fffffff,0);
        int ans=0;
        for(int i=1;i<=k;++i)    ans+=-spfa();
        printf("%d",ans);
    }
  • 相关阅读:
    contentSize、contentInset和contentOffset区别 分类: iphone开发
    iOS设计模式——Category
    如何更好地限制一个UITextField的输入长度
    UIApplication sharedApplication详细解释-IOS
    IOS --- 对象归档
    iOS 数据持久化之使用NSUserDefaults存储数据
    判断素数 一个数的约数 一个整数的幂次约分
    埃氏筛法
    双六(扩展欧几里得算法)
    矩阵快速幂 模板
  • 原文地址:https://www.cnblogs.com/cellular-automaton/p/8317922.html
Copyright © 2020-2023  润新知