HDOJ 4185 - Oil Skimming 离散化后二分图匹配...

              题意:

                       给了一个N*N的图...#代表可能的油田..而油田是由1*2 or 2*1的长方形构成的...问最多有多少个的确是油田...

              题解:

                      把点分成奇偶的(不分也行..结果除以二)...然后跑匈牙利就是..但是..直接搞会超时..可能#是比较少的把..离散化出来效率瞬间就叼炸天了.....


Program:

#include<iostream>
#include<stdio.h>
#include<string.h>
#include<cmath>
#include<queue>
#include<stack>
#include<set>
#include<time.h>
#include<map>
#include<algorithm>
#define ll long long
#define eps 1e-5
#define oo 1<<30
#define pi acos(-1.0)
#define MAXN 360000
#define MAXM 360000
using namespace std;   
struct node
{
       int y,next;
}line[MAXM];
int Lnum,_next[MAXN],match[MAXN];
bool used[MAXN];
char s[605][605];
void addline(int x,int y)
{
       line[++Lnum].next=_next[x],_next[x]=Lnum,line[Lnum].y=y;
}
bool dfs(int x)
{
       for (int k=_next[x];k;k=line[k].next)
       {
               int y=line[k].y;
               if (used[y]) continue;
               used[y]=true;
               if (!match[y] || dfs(match[y]))
               {
                       match[y]=x;
                       return true;
               }
       }
       return false;
}
int getmax(int n)
{
       int sum=0;
       memset(match,0,sizeof(match));
       for (int i=1;i<=n;i++)
       {
              memset(used,false,sizeof(used));
              sum+=dfs(i);
       }
       return sum;
}
int main()
{       
       int cases,n,T,i,j,num; 
       scanf("%d",&T);      
       for (cases=1;cases<=T;cases++)
       { 
               scanf("%d",&n);
               for (i=0;i<n;i++) scanf("%s",s[i]);
               Lnum=0,memset(_next,0,sizeof(_next));
               num=0;
               for (i=0;i<n;i++)
                  for (j=0;j<n;j++)
                      if (s[i][j]=='#' && (i+j)%2==0) 
                      { 
                             num++;
                             if (i && s[i-1][j]=='#') addline(num,(i-1)*n+j); 
                             if (j && s[i][j-1]=='#') addline(num,i*n+j-1);
                             if (i!=n-1 && s[i+1][j]=='#') addline(num,(i+1)*n+j); 
                             if (j!=n-1 && s[i][j+1]=='#') addline(num,i*n+j+1);
                      }
               printf("Case %d: %d\n",cases,getmax(num));
       }      
       return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值