bzoj4657 tower (最小割)
4657: tower
我太蠢了;
只有横向和纵向的炮塔会冲突,所以考虑每个格子拆成两个点,横向经过和纵向经过;
横点向纵点连流量\(inf\)的边,表示横纵中选一个;
对于每个炮塔,沿着炮塔方向串成一条链;
\(S\)连横向炮塔,流量\(inf\),横向链连边\(u->v\)表示选\(u\),流量为链上最大权值\(-w[u]\);
纵向炮塔连\(T\),流量\(inf\),纵向链连边\(u->v\)表示选\(v\),流量为链上最大权值\(-w[v]\);
答案为\(Sigma\)链上最大权值\(-\)最小割;
AC GET☆DAZE
#include<algorithm>
#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<map>
#include<set>
#define N 5039
#define mod 20070831
#define inf 0x3f3f3f3f
#define ll long long
using namespace std;
struct edge
{
int to,next,cap;
}net[N*10];
int ans,sum,S,T,tot=-1,head[N],dis[N];
int n,m,wa[139][139];
void add(int u,int v,int k)
{
net[++tot]=(edge){v,head[u],k},head[u]=tot;
net[++tot]=(edge){u,head[v],0},head[v]=tot;
}
bool bfs()
{
memset(dis,-1,sizeof(dis));
queue<int> que;
int stp;
que.push(S),dis[S]=0;
while(!que.empty())
{
stp=que.front(),que.pop();
for(int a=head[stp];~a;a=net[a].next)
{
if(net[a].cap && !~dis[net[a].to])
{
dis[net[a].to]=dis[stp]+1;
que.push(net[a].to);
}
}
}
return dis[T]!=-1;
}
int dfs(int pos,int flow)
{
if(pos==T || !flow) return flow;
int res=0,stp;
for(int a=head[pos];~a && flow;a=net[a].next)
{
if(net[a].cap && dis[net[a].to]==dis[pos]+1)
{
stp=dfs(net[a].to,min(flow,net[a].cap));
net[a].cap-=stp,net[a^1].cap+=stp;
flow-=stp,res+=stp;
}
}
if(!res) dis[pos]=-1;
return res;
}
void dinic()
{
ans=0;
while(bfs()) ans+=dfs(S,inf);
}
int main()
{
memset(head,-1,sizeof(head));
scanf("%d%d",&n,&m);
for(int a=1;a<=n;a++)
{
for(int b=1;b<=m;b++)
{
scanf("%d",&wa[a][b]);
}
}
S=0,T=n*m*2+1;
for(int a=1;a<=n;a++)
{
for(int b=1,c=0;b<=m;b++,c=0)
{
add((a-1)*m+b,n*m+(a-1)*m+b,inf);
switch(wa[a][b])
{
case -1:
add(S,(a-1)*m+b,inf);
for(int d=a-1;d;d--) if(wa[d][b]>wa[c][b]) c=d;
for(int d=a-1;d>c;d--) add((d-1)*m+b,(d-2)*m+b,wa[c][b]-wa[d][b]);
add((a-1)*m+b,(a-2)*m+b,wa[c][b]);
sum+=wa[c][b];
break;
case -2:
add(S,(a-1)*m+b,inf);
for(int d=a+1;d<=n;d++) if(wa[d][b]>wa[c][b]) c=d;
for(int d=a+1;d<c;d++) add((d-1)*m+b,d*m+b,wa[c][b]-wa[d][b]);
add((a-1)*m+b,a*m+b,wa[c][b]);
sum+=wa[c][b];
break;
case -3:
add(n*m+(a-1)*m+b,T,inf);
for(int d=b-1;d;d--) if(wa[a][d]>wa[a][c]) c=d;
for(int d=b-1;d>c;d--) add(n*m+(a-1)*m+d-1,n*m+(a-1)*m+d,wa[a][c]-wa[a][d]);
add(n*m+(a-1)*m+b-1,n*m+(a-1)*m+b,wa[a][c]);
sum+=wa[a][c];
break;
case -4:
add(n*m+(a-1)*m+b,T,inf);
for(int d=b+1;d<=m;d++) if(wa[a][d]>wa[a][c]) c=d;
for(int d=b+1;d<c;d++) add(n*m+(a-1)*m+d+1,n*m+(a-1)*m+d,wa[a][c]-wa[a][d]);
add(n*m+(a-1)*m+b+1,n*m+(a-1)*m+b,wa[a][c]);
sum+=wa[a][c];
break;
}
}
}
dinic();
printf("%d",sum-ans);
return 0;
}
散りぬべき 時知りてこそ 世の中の 花も花なれ 人も人なれ