제목 설명 Description
< 문제 설명: m * n 개의 격자 가 있 는 바둑판 에서 각 격자 에 정수 가 있 습 니 다.현 재 는 격자 에서 수 를 뽑 아 임의의 두 개의 숫자 가 있 는 격자 가 공공 변 이 없 도록 하고 꺼 낸 수의 총계 가 가장 크다.요 구 를 만족 시 키 는 취 수 알고리즘 을 시험 적 으로 설계 하 다.< 프로 그래 밍 임무: 주어진 격자 바둑판 에 대해 취 수 요구 에 따라 프로 그래 밍 하여 총 과 최대 의 수 를 찾 습 니 다.
입력 설명 Input Description
첫 줄 에는 두 개의 정수 m 와 n 이 있 는데 각각 바둑판 의 줄 수 와 열 수 를 나타 낸다.다음 m 줄 은 줄 마다 n 개의 정수 가 있어 바둑판 격자 중의 수 를 나타 낸다.
출력 설명 Output Description
취 수의 최대 합계 출력
샘플 입력 Sample Input
3 3 1 2 3 3 2 3 2 3 1
샘플 출력 Sample Output
11
데이터 범위 및 알림 Data Size & Hint
n,m<=30
제목 은 여기에 제출 할 수 있 습 니 다:http://wikioi.com/homework/23/
분석: 2 분 그림 의 최대 점 권 독립 집합 모델 은 행렬 안의 각 점 을 두 개의 점 으로 나 누 었 다. i 와 i + n * m, 그리고 S 는 각 i 에 게 변 을 만 들 었 고 권 치 는 이 점 의 값 이 었 다. 그 다음 에 각 i + n * m 는 외환 점 T 에 변 을 만 들 었 다. 권 치 는 이 점 의 값 이 고 각 점 은 그 주변 네 개의 점 에 변 을 만 들 었 다. 권 치 는 무한대 이 고 최대 흐름 을 달리 면 된다.
코드:
//Isap , O(n^2m)
#pragma comment(linker,"/STACK:102400000,102400000")
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;
typedef long long ll; //
const int maxn=2000;
const int maxm=1000005;
const int INF=1000000000;
struct EdgeNode
{
int from;
int to;
int cost;
int next;
}edge[maxm];
int head[maxn],cnt;
void add(int x,int y,int z)
{
edge[cnt].from=x;edge[cnt].to=y;edge[cnt].cost=z;edge[cnt].next=head[x];head[x]=cnt++;
edge[cnt].from=y;edge[cnt].to=x;edge[cnt].cost=0;edge[cnt].next=head[y];head[y]=cnt++;
}
void init()
{
cnt=0;
memset(head,-1,sizeof(head));
}
int S,T,n,m;
int d[maxn],gap[maxn],curedge[maxn],pre[maxn];
//curedge[] ,pre
int sap(int S,int T,int n) //n
{
int cur_flow,flow_ans=0,u,tmp,neck,i;
memset(d,0,sizeof(d));
memset(gap,0,sizeof(gap));
memset(pre,-1,sizeof(pre));
for(i=0;i<=n;i++)curedge[i]=head[i]; //
gap[0]=n;
u=S;
while(d[S]=n ,
{
if(u==T)
{
cur_flow=INF;
for(i=S;i!=T;i=edge[curedge[i]].to)
{ // ,
if(cur_flow>edge[curedge[i]].cost)
{
neck=i;
cur_flow=edge[curedge[i]].cost;
}
}
for(i=S;i!=T;i=edge[curedge[i]].to)
{ //
tmp=curedge[i];
edge[tmp].cost-=cur_flow;
edge[tmp^1].cost+=cur_flow;
}
flow_ans+=cur_flow;
u=neck; //
}
for(i=curedge[u];i!=-1;i=edge[i].next)
if(edge[i].cost&&d[u]==d[edge[i].to]+1)
break;
if(i!=-1)
{
curedge[u]=i;
pre[edge[i].to]=u;
u=edge[i].to;
}
else
{
if(0==--gap[d[u]])break; //gap
curedge[u]=head[u];
for(tmp=n,i=head[u];i!=-1;i=edge[i].next)
if(edge[i].cost)
tmp=min(tmp,d[edge[i].to]);
d[u]=tmp+1;
++gap[d[u]];
if(u!=S)u=pre[u]; //
}
}
return flow_ans;
}
int mp[35][35];
int dis[5][3]={{0,1},{0,-1},{1,0},{-1,0}};
int yj(int x,int y)
{
if(x<1||x>n||y<1||y>m)return 1;
return 0;
}
void build()
{
int i,j,k,x,y,t=n*m,a,b;
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
a=(i-1)*m+j;
add(S,a,mp[i][j]);
add(a+t,T,mp[i][j]);
}
}
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
for(k=0;k<4;k++){
x=i+dis[k][0]; y=j+dis[k][1];
if(!yj(x,y)){
a=(i-1)*m+j;
b=(x-1)*m+y;
add(a,b+t,INF);
}
}
}
}
}
int main()
{
int ans,i,j;
while(~scanf("%d%d",&n,&m))
{
init(); S=0; T=n*m*2+1; ans=0;
for(i=1;i<=n;i++)
for(j=1;j<=m;j++)
scanf("%d",&mp[i][j]),ans+=mp[i][j];
build();
printf("%d ",ans-sap(S,T,T+1)/2);
}
return 0;
}
현재 기사가 여러분의 문제를 해결하지 못하는 경우 AI 엔진은 머신러닝 분석(스마트 모델이 방금 만들어져 부정확한 경우가 있을 수 있음)을 통해 가장 유사한 기사를 추천합니다:
Codeforces277 E. Binary Tree on Plane 최소 비용 최대 흐름
Codeforces277 E.
Binary Tree on Plane 최소 비용 최대 흐름
전송문:https://codeforces.com/contest/277/problem/E
평면에 n개의 점(2≤n≤400)을 주...
텍스트를 자유롭게 공유하거나 복사할 수 있습니다.하지만 이 문서의 URL은 참조 URL로 남겨 두십시오.
CC BY-SA 2.5, CC BY-SA 3.0 및 CC BY-SA 4.0에 따라 라이센스가 부여됩니다.