题目链接:点击打开链接
刚开始拿到这个题目的时候以为是高斯消元法,对于每个方格四周的边的数量设未知数解方程,后面仔细想了想,缺乏可行性,时间复杂度和空间复杂度太高了。后面终于想到网络流上面去了,可是对于每个点都要控制流量,而且每条边的流量又被多个点控制,然后越想越迷糊。
想了两天了终于意识到这个是个二分图,然后二分图根据每个点的颜色,选择与源点或者汇点建边,点与点之间根据能否增流建边。(写的很粗糙,不负责地说下次什么时候想起来的时候再改改吧~~~~~)
#include <iostream>
#include <algorithm>
#include <cstdio>
#include <cstring>
#include <vector>
using namespace std;
const int inf=0x3f3f3f3f;
const int N=200;
int L[]={0,1,0,-1};
int R[]={1,0,-1,0};
char Graph[N<<1][N<<1];
struct edge_t
{
int v,c,next;
}edge[N*N*4];
int Ecnt;
int vertex[N*N];
void init_Graph()
{
Ecnt=0;
memset(vertex,-1,sizeof(vertex));
}
void make_edge(int u,int v,int c)
{
edge[Ecnt].v=v;
edge[Ecnt].c=c;
edge[Ecnt].next=vertex[u];
vertex[u]=Ecnt++;
edge[Ecnt].v=u;
edge[Ecnt].c=0;
edge[Ecnt].next=vertex[v];
vertex[v]=Ecnt++;
}
int LL[N*N];
bool bfs(int s,int t)
{
memset(LL,-1,sizeof(LL));
vector<int> q;
q.push_back(s);
LL[s]=0;
while(!q.empty())
{
int u=q.back();
q.pop_back();
for(int i=vertex[u]; i!=-1; i=edge[i].next)
{
if(edge[i].c<=0) continue;
int v=edge[i].v;
if(-1!=LL[v]) continue;
q.push_back(v);
LL[v]=LL[u]+1;
}
}
return -1!=LL[t];
}
int dfs(int u,int cf,int t)
{
if(u==t) return cf;
int tf=0;
for(int i=vertex[u]; i!=-1; i=edge[i].next)
{
int v=edge[i].v;
int c=edge[i].c;
if(LL[u]+1==LL[v]&&c>0&&cf>tf)
{
int f=dfs(v,min(c,cf-tf),t);
if(0==f) continue;
edge[i].c-=f;
edge[i^1].c+=f;
tf+=f;
}
}
if(0==tf) LL[u]=-1;
return tf;
}
int Dinic(int s,int t)
{
int ret=0;
while(bfs(s,t))
{
int ans;
while(ans=dfs(s,inf,t))
ret+=ans;
}
return ret;
}
inline int Gethash(int x,int y,int N)
{
return x*N+y;
}
int main()
{
int N;
while(scanf("%d",&N)!=EOF)
{
init_Graph();
int s=(N+1)*(N+1),e=(N+1)*(N+1)+1;
//唯一难点,边缘上的点怎么建图
for(int i=0;i<2*N-1;i++)
scanf("%s",Graph[i]);
for(int i=0;i<=N;i++)
for(int j=0;j<=N;j++)
{
//因为是二分图,所以染色
int color=(i+j)%2;
int flow=(i==0||j==0||i==N||j==N)?4:3;
int x=2*i-1,y=2*j-1;
for(int k=0;k<4;k++)
{
int m=x+L[k],n=y+R[k];
if(m>=0&&m<2*N-1&&n>=0&&n<2*N-1&&Graph[m][n]=='.')
{
make_edge(Gethash(i,j,N+1),Gethash(i+L[k],j+R[k],N+1),1);
}
else flow--;
}
if(color==0) make_edge(s,Gethash(i,j,N+1),flow);
else make_edge(Gethash(i,j,N+1),e,flow);
}
printf("%d\n",Dinic(s,e)+1);
}
return 0;
}