- 题意: 给出一个方格取数,最多能取k次,问最多能取到多少
- 思路: 最大费用最大流
#include
#include
#include
#include
#include
#include
#include
#include
#define ll long long
using namespace std;
typedef pair pii;
const int N = 1e5+10;
const int INF = 0x3f3f3f3f;
struct E{
int u,v,flow,nxt,w;
E(){}
E(int u,int v,int flow,int nxt,int w):u(u),v(v),flow(flow),nxt(nxt),w(w){}
}e[N*2];
int n,m,k,sp,tp,tot;
int head[N],dis[N],pre[N],cur[N],vis[N];
ll cost;
void init(){
tot = 0; memset(head,-1,sizeof head);
}
void addE(int u,int v,int flow,int cost){
e[tot].u = u; e[tot].v = v; e[tot].flow = flow; e[tot].nxt = head[u]; e[tot].w = cost; head[u] = tot++;
e[tot].u = v; e[tot].v = u; e[tot].flow = 0; e[tot].nxt = head[v]; e[tot].w = -cost; head[v] = tot++;
}
int q[N];
int bfs(){
int qtop = 0,qend=0;
memset(vis,0,sizeof vis);
memset(dis,0x3f,sizeof dis);
dis[sp] = 0;
q[qend++] = sp;
while(qtop!=qend){
int u = q[qtop++];
vis[u] = 0;
// if(u==tp) return true;
for(int i=head[u];~i;i=e[i].nxt){
int v = e[i].v;
if(dis[v]>dis[u]+e[i].w && e[i].flow){
dis[v] = dis[u]+e[i].w;
if(!vis[v])
q[qend++] = v,vis[v] = 1;
}
}
}
return dis[tp]!= INF;
}
int dfs(int u,int flow){
int res = 0;
if(u==tp) return flow;
vis[u] = 1;
for(int i=head[u];i!=-1&&flow;i=e[i].nxt){
int v = e[i].v;
if(!vis[v] && dis[v]==dis[u]+e[i].w && e[i].flow){
int d = dfs(v,min(e[i].flow,flow));
e[i].flow -=d;
e[i^1].flow += d;
res+=d;
flow -= d;
cost += d*e[i].w;
}
}
vis[u] = 0;
if(!res)
dis[u] = -2;
return res;
}
int dinic(){
int ans=0;
while(bfs()){
ans+=dfs(sp,INF);
}
return ans;
}
int main(){
scanf("%d%d%d",&k,&m,&n);
init();
sp = n*m*2+1,tp = sp + 1;
int cp,val,step = n*m;
for(int i=1;i<=n;++i){
for(int j=1;j<=m;++j){
scanf("%d",&val);
cp = (i-1)*m + j;
addE(cp,cp+step,1,-val); // 流量为1,每个点只能被取一次
addE(cp,cp+step,k,0); // 流量为k,可以经过k次
if(i
题目