★ 격자 취 수 32 분 그림 의 최대 점 권 독립 집합

제목 설명 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; }

좋은 웹페이지 즐겨찾기