bzoj4657 tower (最小割)

4657: tower

Time Limit: 10 Sec Memory Limit: 256 MB
Submit: 92 Solved: 49
[Submit][Status][Discuss]
## Description Nick最近在玩一款很好玩的游戏,游戏规则是这样的: 有一个n*m的地图,地图上的每一个位置要么是空地,要么是炮塔,要么是一些BETA狗,Nick需要操纵炮塔攻击BETA狗们。 攻击方法是:对于每个炮塔,游戏系统已经给出它可以瞄准的方向(上下左右其中一个),Nick需要选择它的攻击位置,每一个炮塔只能够攻击一个位置,炮塔只能够向着它的瞄准方向上的某个位置发动攻击,当然炮塔也可以不进行攻击。炮塔威力强大,它可以且仅可以消灭目标位置上所有的BETA狗。出于安全考虑,游戏系统已经保证不存在一个炮塔能够瞄准另外一个炮塔,即对于任意一个炮塔,它所有可能的攻击位置上不存在另外一个炮塔。而且,如果把炮塔的起点和终点称为炮弹的运行轨迹,那么系统不允许两条轨迹相交f包括起点和终点)。 现在,选定目标位置以后,每一个炮塔同时开炮,你要告诉Nick,他最多可以干掉多少BETA狗。 ## Input 第一行两个正整数n,m,表示地图的规模。 接下来礼行,每行m个整数,0表示空地,-1,-2,一3,-4分别表示瞄准上下左右的炮塔,若为正整数p,则表示该位置有p个BETA狗。 n,m <= 50,每个位置的BETA狗数量不超过999个,保证不存在任意一个炮塔能够瞄准另外一个炮塔 ## Output 一个正整数,表示Nick最多可以干掉几个BETA狗

我太蠢了;
只有横向和纵向的炮塔会冲突,所以考虑每个格子拆成两个点,横向经过和纵向经过;
横点向纵点连流量(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;
}
原文地址:https://www.cnblogs.com/Sinogi/p/8659880.html