行染色条->列染色条 代表一个能放的点。可以用二分图匹配做。
网络流做法
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int N=2509,M=7509*2,inf=0x7fffffff;
int head[N],d[N],edge[M],ver[M],next[M];
int tot=1,n,m,maxflow=0,T;
int h[100][100],l[100][100],t1=0,t2=0,s,t;
bool h1[N],l1[N];
char map[100][100];
void add (int u,int v,int cap) {
ver[++tot]=v;edge[tot]=cap;next[tot]=head[u];head[u]=tot;
ver[++tot]=u;edge[tot]=0; next[tot]=head[v];head[v]=tot;
}
bool bfs () {
memset(d,0,sizeof(d));
queue<int> q;
q.push(s); d[s]=1;
while (!q.empty()) {
int x=q.front(); q.pop();
for (int i=head[x];i;i=next[i])
if (edge[i] && d[ver[i]]==0) {
q.push(ver[i]);
d[ver[i]]=d[x]+1;
if (ver[i]==t) return true;
}
}
return false;
}
int dinic (int x,int f) {
if (x==t) return f;
int rest=f,now;
for (int i=head[x];i&&rest;i=next[i])
if (edge[i]&&d[ver[i]]==d[x]+1) {
now=dinic(ver[i],min(rest,edge[i]));
if (!now) d[ver[i]]=0;
edge[i]-=now;
edge[i^1]+=now;
rest-=now;
}
return f-rest;
}
int main () {
int tmp;bool flag=0;
scanf("%d",&T);
for (int k=1;k<=T;k++) {
scanf("%d%d%*c",&m,&n);
t1=t2=0;tot=1;
maxflow=0;
memset(h,0,sizeof(h));
memset(l,0,sizeof(l));
memset(h1,0,sizeof(h1));
memset(l1,0,sizeof(l1));
memset(head,0,sizeof(head));
for (int i=1;i<=m;i++) {
for (int j=1;j<=n;j++) {
scanf("%c",&map[i][j]);
}
scanf("%*c");
}
for (int i=1;i<=m;i++) {
flag=0;
for (int j=1;j<=n;j++)
if (map[i][j]=='o') {
if (!flag) t1++;
h[i][j]=t1;flag=1;
}
else if (map[i][j]=='#') flag=0;
}
for (int j=1;j<=n;j++) {
flag=0;
for (int i=1;i<=m;i++)
if (map[i][j]=='o') {
if (!flag) t2++;
l[i][j]=t2;flag=1;
}
else if (map[i][j]=='#') flag=0;
}
s=0;t=t1+t2+1;
for (int i=1;i<=m;i++)
for (int j=1;j<=n;j++)
if (map[i][j]=='o')
add(h[i][j],l[i][j]+t1,1);
for (int i=1;i<=t1;i++)
add(s,i,1); //这里是1不是inf
for (int i=1;i<=t2;i++)
add(i+t1,t,1);
while (b````````````
s())
while (tmp=dinic(s,inf)) maxflow+=tmp;
printf("Case :%d\n%d\n",k,maxflow);
}
}
匈牙利算法做法
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <queue>
using namespace std;
const int N=2509,M=7509*2,inf=0x3fffffff;
int head[N],edge[M],ver[M],next[M];
int tot=1,n,m,ans=0,T;
int h[100][100],l[100][100],t1=0,t2=0,s,t;
int cx[N],cy[N],sx[N],sy[N];
char map[100][100];
void add (int u,int v,int cap) {
ver[++tot]=v;edge[tot]=cap;next[tot]=head[u];head[u]=tot;
}
int path (int u) {
sx[u]=1;int v;
for (int i=head[u];i;i=next[i]) {
if (!sy[v=ver[i]]) {
sy[v]=1;
if (!cy[v]||path(cy[v])) {
cx[u]=v;cy[v]=u;
return 1;
}
}
}
return 0;
}
void solve () {
ans=0;
memset(cx,0,sizeof(cx));
memset(cy,0,sizeof(cy));
for (int i=1;i<=t1;i++)
if (!cx[i]) {
memset(sx,0,sizeof(sx));
memset(sy,0,sizeof(sy));
ans+=path(i);
}
}
int main () {
int tmp;bool flag=0;
scanf("%d",&T);
for (int k=1;k<=T;k++) {
scanf("%d%d%*c",&m,&n);
t1=t2=0;tot=1;
memset(h,0,sizeof(h));
memset(l,0,sizeof(l));
memset(head,0,sizeof(head));
for (int i=1;i<=m;i++) {
for (int j=1;j<=n;j++) {
scanf("%c",&map[i][j]);
}
scanf("%*c");
}
for (int i=1;i<=m;i++) {
flag=0;
for (int j=1;j<=n;j++)
if (map[i][j]=='o') {
if (!flag) t1++;
h[i][j]=t1;flag=1;
}
else if (map[i][j]=='#') flag=0;
}
for (int j=1;j<=n;j++) {
flag=0;
for (int i=1;i<=m;i++)
if (map[i][j]=='o') {
if (!flag) t2++;
l[i][j]=t2;flag=1;
}
else if (map[i][j]=='#') flag=0;
}
for (int i=1;i<=m;i++)
for (int j=1;j<=n;j++)
if (map[i][j]=='o')
add(h[i][j],l[i][j]+t1,1);
solve();
printf("Case :%d\n%d\n",k,ans);
}
return 0;
}