4185 Oil Skimming 最大匹配 奇偶建图

题目大意:

  统计相邻(上下左右)的‘#’的对数。

解法:

  与题目hdu1507 Uncle Tom's Inherited Land*类似,需要用奇偶建图。就是行+列为奇数的作为X集合,偶尔作为Y集合,都是‘#’就连边。最后求最大匹配。

  数据有点大,直接建图会出错(我试过)。可以按照‘#’出现的顺序给顶点编号。

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<queue>
  5 #include<vector>
  6 #include<algorithm>
  7 using namespace std;
  8 const int N=36005,INF=0x3f3f3f3f;
  9 int cx[N],cy[N],dx[N],dy[N];
 10 bool bmask[N];
 11 vector<int > bmap[N];
 12 int nx,ny,dis,ans;
 13 bool searchpath()
 14 {
 15     queue<int> q;
 16     dis=INF;
 17     memset(dx,-1,sizeof(dx));
 18     memset(dy,-1,sizeof(dy));
 19     for(int i=1;i<=nx;i++)
 20     {
 21         if(cx[i]==-1){ q.push(i); dx[i]=0; }
 22         while(!q.empty())
 23         {
 24             int u=q.front(); q.pop();
 25             if(dx[u]>dis) break;
 26             for(int i=0;i<bmap[u].size();i++)
 27             {
 28                 int v=bmap[u][i];
 29                 if(dy[v]==-1)
 30                 {
 31                     dy[v]= dx[u] + 1;
 32                     if(cy[v]==-1) dis=dy[v];
 33                     else
 34                     {
 35                         dx[cy[v]]= dy[v]+1;
 36                         q.push(cy[v]);
 37                     }
 38                 }
 39             }
 40         }
 41     }
 42     return dis!=INF;
 43 }
 44 int findpath(int u)
 45 {
 46     for(int i=0;i<bmap[u].size();i++)
 47     {
 48         int v=bmap[u][i];
 49         if(!bmask[v]&&dy[v]==dx[u]+1)
 50         {
 51             bmask[v]=1;
 52             if(cy[v]!=-1&&dy[v]==dis) continue;
 53             if(cy[v]==-1||findpath(cy[v]))
 54             {
 55                 cy[v]=u; cx[u]=v;
 56                 return 1;
 57             }
 58         }
 59     }
 60     return 0;
 61 }
 62 void maxmatch()
 63 {
 64     ans=0;
 65     memset(cx,-1,sizeof(cx));
 66     memset(cy,-1,sizeof(cy));
 67     while(searchpath())
 68     {
 69         memset(bmask,0,sizeof(bmask));
 70         for(int i=1;i<=nx;i++)
 71             if(cx[i]==-1) ans+=findpath(i);
 72     }
 73 }
 74 void init()
 75 {
 76     for(int i=0;i<=N;i++) bmap[i].clear();
 77 }
 78 char s[605][605];
 79 int Map[605][605];
 80 int main()
 81 {
 82     //freopen("test.txt","r",stdin);
 83     int cas,n,i,j,k=1,a,b,t=1;
 84     char ch;
 85     scanf("%d",&cas);
 86     while(cas--)
 87     {
 88         scanf("%d",&n);
 89         t=0;
 90         for(i=1;i<=n;i++){
 91             getchar();
 92             for(j=1;j<=n;j++)
 93             {
 94                 scanf("%c",&s[i][j]);
 95                 if(s[i][j]=='#') Map[i][j]=++t;
 96             }
 97         }
 98         init();
 99         for(i=1;i<=n;i++)
100         {
101             for(j=1;j<=n;j++)
102             {
103                 if(s[i][j]=='#'&&((i+j)%2))
104                 {
105                     a=Map[i][j];
106                     if(i>1&&s[i-1][j]=='#'){
107                         b=Map[i-1][j];
108                         bmap[a].push_back(b);
109                     }
110                     if(i<n&&s[i+1][j]=='#'){
111                         b=Map[i+1][j];
112                         bmap[a].push_back(b);
113                     }
114                     if(j>1&&s[i][j-1]=='#'){
115                         b=Map[i][j-1];
116                         bmap[a].push_back(b);
117                     }
118                     if(j<n&&s[i][j+1]=='#'){
119                         b=Map[i][j+1];
120                         bmap[a].push_back(b);
121                     }
122                 }
123             }
124         }
125         nx=t;
126         maxmatch();
127         printf("Case %d: %d
",k++,ans);
128     }
129     return 0;
130 }
View Code
原文地址:https://www.cnblogs.com/Potato-lover/p/3991533.html