zoukankan      html  css  js  c++  java
  • POJ 3422 Kaka's Matrix Travels

    题目链接:ヾ(≧∇≦*)ゝ

    大致题意:给你一个(n*n)的矩阵从((1,1))出发,到((n,n))结束,只能走右边或左边。每个点在被走过之后权值变成0,问走(k)次后,能获得的最大值总和是多少

    Solution:

    看数据范围,(nle50,0le k le10),再结合题目,一下子就能想到费用流

    那么,该如何建图呢?

    我们看一下限制:

    首先,每一个点只能贡献一次价值,如何来解决这个问题呢?

    拆点。把每个点分为入点和出点,入点和出点之间的费用为该点权值,容量为1,这样就能够解决这条限制。

    然后,再把每一个点的出点与它右边的点的入点和下面的点的入点连边,费用为0,容量为k

    再是能够走k次,我们建立一个超级源点和超级汇点,拿出发点的入点与源点连边,容量为k,费用为0,结束点的出点与汇点连边,容量为k,费用为0

    不过,仅仅这样是不行的。按照上述的建图,我们发现它只能应对(kle2)的情况,最多跑完两次最大费用流,它就会无路可走,所以我们还需要连一些边。

    对于每一个点,将它的出点与它右边点的的出点,下面点的出点都连一条容量为k,费用为0的边。

    这是什么意思呢?这条边代表只是经过这个点,而不取该点的权值。

    最后跑最大费用流,拿答案减去多加的出发点和结束点的权值,就是答案了

    不过,当(k=0)时,需要特判一下,直接输出0。(博主就是因为忘记特判而狂WA不止啊...)

    Code:

    #include<queue>
    #include<cstdio>
    #include<ctype.h>
    #include<cstring>
    #include<algorithm>
    #define N 30001
    #define inf 0x8f
    using namespace std;
    int S,T,n,k,cnt=1,tot;
    int head[N],mp[51][51];
    struct Edge{int nxt,to,v,w;}edge[N];
    void ins(int x,int y,int z,int w){
        edge[++cnt].nxt=head[x];
        edge[cnt].to=y;edge[cnt].v=z;
        edge[cnt].w=w;head[x]=cnt;
    }
    namespace Network_Flow{
        queue<int> q;
        int maxcost,delta;
        int dis[N],vis[N],pre[N];
        int spfa(){
            pre[T]=0;delta=inf;
            memset(vis,0,sizeof(vis));
            memset(dis,255,sizeof(dis));
            q.push(S);vis[S]=1;dis[S]=0;
            while(!q.empty()){
                int x=q.front();q.pop();vis[x]=0;
                for(int i=head[x];i;i=edge[i].nxt){
                    int y=edge[i].to;
                    if(edge[i].v&&dis[x]+edge[i].w>dis[y]){
                        dis[y]=dis[x]+edge[i].w;
                        delta=min(delta,edge[i].v);
                        pre[y]=i;if(!vis[y]) q.push(y),vis[y]=1;
                    }
                }
            }
            return pre[T];
        }
        void update(){
            int x=T;
            while(x!=1){
                int i=pre[x];
                edge[i].v-=delta;
                edge[i^1].v+=delta;
                x=edge[i^1].to;
            }
            maxcost+=dis[T]*delta;
        }
        void Edmond_Karp(){
            while(spfa()) update();
            printf("%d
    ",maxcost-(k-1)*(mp[1][1]+mp[n][n]));
        }
    }
    int num(int i,int j){return (i-1)*n*2+j*2;}
    int read(){
        int x=0,f=1;char ch=getchar();
        while(!isdigit(ch)){if(ch=='-')f=-f;ch=getchar();}
        while(isdigit(ch)){x=x*10+ch-48;ch=getchar();}
        return x*f;
    }
    int main(){
        n=read(),k=read();S=n*n*2+1,T=S+1;
        using namespace Network_Flow;
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                mp[i][j]=read();tot+=2;
                if((i==1&&j==1)||(i==n&&j==n)){
                    ins(tot-1,tot,k,mp[i][j]);
                    ins(tot,tot-1,0,-mp[i][j]);
                    continue;
                }
                ins(tot-1,tot,1,mp[i][j]);
                ins(tot,tot-1,0,-mp[i][j]);
            }
        if(!k){printf("0");return 0;}
        ins(S,1,inf,0);ins(1,S,0,0);
        ins(tot,T,inf,0);ins(T,tot,0,0);
        for(int i=1;i<=n;i++)
            for(int j=1;j<=n;j++){
                if(i<n){
                    ins(num(i,j),num(i+1,j)-1,k,0);
                    ins(num(i+1,j)-1,num(i,j),0,0);
                    ins(num(i,j),num(i+1,j),k,0);
                    ins(num(i+1,j),num(i,j),0,0);
                }
                if(j<n){
                    ins(num(i,j),num(i,j+1)-1,k,0);
                    ins(num(i,j+1)-1,num(i,j),0,0);
                    ins(num(i,j),num(i,j+1),k,0);
                    ins(num(i,j+1),num(i,j),0,0);
                }
            }
        Edmond_Karp();
        return 0;
    }
    
  • 相关阅读:
    LeetCode Binary Tree Inorder Traversal
    LeetCode Populating Next Right Pointers in Each Node
    LeetCode Construct Binary Tree from Inorder and Postorder Traversal
    LeetCode Reverse Linked List II
    LeetCode Populating Next Right Pointers in Each Node II
    LeetCode Pascal's Triangle
    Palindrome Construct Binary Tree from Preorder and Inorder Traversal
    Pascal's Triangle II
    LeetCode Word Ladder
    LeetCode Binary Tree Zigzag Level Order Traversal
  • 原文地址:https://www.cnblogs.com/NLDQY/p/10333559.html
Copyright © 2011-2022 走看看