zoukankan      html  css  js  c++  java
  • 【wikioi】1227 方格取数 2(费用流)

    http://www.wikioi.com/problem/1227

    裸题,拆点,容量为1,费用为点权的负数(代表只能取一次)。再在拆好的两个点连边,容量为oo,费用为0。(代表能取0)

    然后向右和下连边,容量我oo,费用为0

    最后跑一次最小费用,取绝对值就是答案。

    #include <cstdio>
    #include <cstring>
    #include <cmath>
    #include <string>
    #include <iostream>
    #include <algorithm>
    using namespace std;
    #define rep(i, n) for(int i=0; i<(n); ++i)
    #define for1(i,a,n) for(int i=(a);i<=(n);++i)
    #define for2(i,a,n) for(int i=(a);i<(n);++i)
    #define for3(i,a,n) for(int i=(a);i>=(n);--i)
    #define for4(i,a,n) for(int i=(a);i>(n);--i)
    #define CC(i,a) memset(i,a,sizeof(i))
    #define read(a) a=getint()
    #define print(a) printf("%d", a)
    #define dbg(x) cout << #x << " = " << x << endl
    #define printarr(a, n, m) rep(aaa, n) { rep(bbb, m) cout << a[aaa][bbb]; cout << endl; }
    inline const int getint() { int r=0, k=1; char c=getchar(); for(; c<'0'||c>'9'; c=getchar()) if(c=='-') k=-1; for(; c>='0'&&c<='9'; c=getchar()) r=r*10+c-'0'; return k*r; }
    inline const int max(const int &a, const int &b) { return a>b?a:b; }
    inline const int min(const int &a, const int &b) { return a<b?a:b; }
    
    const int N=5500, M=1000000, oo=~0u>>1;
    int ihead[N], cnt=1, d[N], p[N], n, k, vis[N], q[N], front, tail;
    struct ED { int from, to, cap, w, next; } e[M];
    inline void add(const int &u, const int &v, const int &c, const int &w) {
    	e[++cnt].next=ihead[u]; ihead[u]=cnt; e[cnt].to=v; e[cnt].from=u; e[cnt].cap=c; e[cnt].w=w;
    	e[++cnt].next=ihead[v]; ihead[v]=cnt; e[cnt].to=u; e[cnt].from=v; e[cnt].cap=0; e[cnt].w=-w;
    }
    inline const bool spfa(const int &s, const int &t) {
    	for1(i, 0, t) d[i]=1000000000, vis[i]=0;
    	vis[s]=1; d[s]=front=tail=0; q[tail++]=s;
    	int u, v, i;
    	while(front!=tail) {
    		u=q[front++]; if(front==N) front=0;
    		for(i=ihead[u]; i; i=e[i].next) if(e[i].cap && d[v=e[i].to]>d[u]+e[i].w) {
    			d[v]=d[u]+e[i].w; p[v]=i;
    			if(!vis[v]) {
    				vis[v]=1, q[tail++]=v;
    				if(tail==N) tail=0;
    			}
    		}
    		vis[u]=0;
    	}
    	return d[t]!=1000000000;
    }
    int mcf(const int &s, const int &t) {
    	int ret=0, f, u;
    	while(spfa(s, t)) {
    		for(f=oo, u=t; u!=s; u=e[p[u]].from) f=min(f, e[p[u]].cap);
    		for(u=t; u!=s; u=e[p[u]].from) e[p[u]].cap-=f, e[p[u]^1].cap+=f;
    		ret+=d[t]*f;
    	}
    	return ret;
    }
    int main() {
    	read(n); read(k);
    	int s=0, t=n*n*2+1, c, now, pw=n*n;
    	for1(i, 1, n) for1(j, 1, n) {
    		read(c); now=(i-1)*n+j;
    		add(now, now+pw, 1, -c); add(now, now+pw, oo, 0);
    		if(i<n) add(now+pw, now+n, oo, 0);
    		if(j<n) add(now+pw, now+1, oo, 0);
    	}
    	add(s, 1, k, 0); add(n*n*2, t, k, 0);
    	printf("%d
    ", -mcf(s, t));
    	return 0;
    }
    

    给出一个n*n的矩阵,每一格有一个非负整数Aij,(Aij <= 1000)现在从(1,1)出发,可以往右或者往下走,最后到达(n,n),每达到一格,把该格子的数取出来,该格子的数就变成0,这样一共走K次,现在要求K次所达到的方格的数的和最大

    第一行两个数n,k(1<=n<=50, 0<=k<=10)

    接下来n行,每行n个数,分别表示矩阵的每个格子的数

    一个数,为最大和

    3 1

    1 2 3

    0 2 1

    1 4 2

    11

    1<=n<=50, 0<=k<=10

  • 相关阅读:
    Atitit.Java exe bat  作为windows系统服务程序运行
    Atitit. Object-c语言 的新的特性  attilax总结
    Atitit. Object-c语言 的新的特性  attilax总结
    Atitit。Time base gc 垃圾 资源 收集的原理与设计
    Atitit。Time base gc 垃圾 资源 收集的原理与设计
    Atitit.go语言golang语言的新的特性  attilax总结
    Atitit.go语言golang语言的新的特性  attilax总结
    Atitit.pdf 预览 转换html attilax总结
    Atitit.pdf 预览 转换html attilax总结
    Atitit.office word  excel  ppt pdf 的web在线预览方案与html转换方案 attilax 总结
  • 原文地址:https://www.cnblogs.com/iwtwiioi/p/3934954.html
Copyright © 2011-2022 走看看