• POJ 3422 Kaka's Matrix Travels | 最小费用最大流


    题目:

    给个n*n的带正权矩阵,k次从(1,1)走到(n,n),每个格子的权值只能获得一次,每次只能向右或下走

    问获得最大权值


    题解:

    求最大权值可以把权值变成负的求最小

    然后考虑怎么约束每个格子的权值,

    把格子拆成两个点,连两条边:一条容量为1,花费为-权值,一条容量为INF,花费为0

    S到第一个格子,连容量为k,最后一个格子的二号点到T,容量为k

    这样就可以限制每个点只有走一次的时候能获得权值,

    跑最小费用最大流

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    #define N 5010
    #define INF 1000000
    using namespace std;
    int ecnt=1,vis[N],dist[N],n,m,S,T,ans,head[N],k,w[N][N];
    deque <int> q;
    inline int get(int x,int y)
    {
        return n*(x-1)+y;
    }
    struct adj
    {
        int nxt,v,w,c;
    }e[N*N];
    inline void add(int u,int v,int w,int c)
    {
        e[++ecnt].v=v,e[ecnt].w=w,e[ecnt].c=c,e[ecnt].nxt=head[u],head[u]=ecnt;
        e[++ecnt].v=u,e[ecnt].w=0,e[ecnt].c=-c,e[ecnt].nxt=head[v],head[v]=ecnt;
    }
    inline int spfa(int s,int t)
    {
        int v;
        memset(vis,0,sizeof(vis));
        for (int i=s;i<=t;i++) dist[i]=INF;
        dist[t]=0,vis[t]=1;
        q.push_back(t);
        while (!q.empty())
        {
        int u=q.front();q.pop_front();
        for (int i=head[u];i;i=e[i].nxt)
            if (e[i^1].w>0 && dist[v=e[i].v]>dist[u]-e[i].c)
            {
            dist[v]=dist[u]-e[i].c;
            if (!vis[v])
            {
                vis[v]=1;
                if (!q.empty() && dist[v]<dist[q.front()])
                q.push_front(v);
                else
                q.push_back(v);
            }
            }
        vis[u]=0;
        }
        return dist[s]<INF;
    }
    inline int dfs(int x,int flow)
    {
        //   puts("DFS");
        if (x==T)
        return vis[T]=1,flow;
        int used=0,tmp,v;
        vis[x]=1;
        for (int i=head[x];i;i=e[i].nxt)
        if (!vis[v=e[i].v] && e[i].w>0 && dist[x]-e[i].c==dist[v])
        {
            tmp=dfs(v,min(e[i].w,flow-used));
            if (tmp>0)
            ans+=tmp*e[i].c,e[i].w-=tmp,e[i^1].w+=tmp,used+=tmp;
            if (used==flow) break;
        }
        return used;
    }
    inline int CostFlow()
    {
        int Flow=0;
        while (spfa(S,T))
        {
        vis[T]=1;
        while (vis[T])
        {
            memset(vis,0,sizeof(vis));
            Flow+=dfs(S,INF);
        }
        }
        return Flow;
    }
    int main()
    {
        scanf("%d%d",&n,&k);
        for (int i=1;i<=n;i++)
    	for (int j=1;j<=n;j++)
    	    scanf("%d",&w[i][j]);
        for (int i=1;i<=n;i++)
    	for (int j=1;j<=n;j++)
    	{
    	    int num=get(i,j);
    	    add(num,num+n*n,1,-w[i][j]);
    	    add(num,num+n*n,k-1,0);
    	    if (i<n) add(n*n+num,get(i+1,j),k,0);
    	    if (j<n) add(n*n+num,get(i,j+1),k,0);
    	}
        S=0,T=n*n+n*n+1;
        add(S,1,k,0);
        add(n*n+get(n,n),T,k,0);
        CostFlow();
        printf("%d",-ans);
        return 0;
    }
    
  • 相关阅读:
    常用编码格式算法
    js显示当前时间
    客户端和服务器端乱码问题
    常用的小技巧
    开发jsp中常用标签
    java中的反射
    java中的单例设计模式
    java中的枚举类
    关于继承时构造方法的问题
    TCP三次握手和四次握手全过程 为什么要三次握手而不是二次握手?
  • 原文地址:https://www.cnblogs.com/mrsheep/p/7954488.html
Copyright © 2020-2023  润新知