HDU 3360 奇偶染色建二分图 或者 拆点双边建二分图
2014-07-18 16:08
246 查看
方法一:
图中的点根据(i+j)%2为奇数或者偶数,划分为二分图,然后建图,直接求出二分最大匹配。
代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <queue>
using namespace std;
const int maxn=2505;
const int maxm=1000005;
struct EdgeNode
{
int to;
int next;
}edge[maxm];
int head[maxn],cnt;
void add(int x,int y)
{
edge[cnt].to=y;
edge[cnt].next=head[x];
head[x]=cnt++;
}
int n,m,v[maxn],pre[maxn];
int d[15][3]={{-1,-2},{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,0},{0,1},{1,0},{0,-1}};
int g[maxn][maxn],jiou[maxn][maxn];
void init()
{
cnt=0;
memset(head,-1,sizeof(head));
}
int dfs(int x)
{
int y;
for(int i=head[x];i!=-1;i=edge[i].next)
{
y=edge[i].to;
if(!v[y]){
v[y]=1;
if(!pre[y]||dfs(pre[y])){
pre[y]=x;
return true;
}
}
}
return false;
}
int erfenpipei()
{
int sum=0;
memset(pre,0,sizeof(pre));
for(int i=1;i<=n;i++){
memset(v,0,sizeof(v));
if(dfs(i))
sum++;
}
return sum;
}
int yj(int x,int y)
{
if(x<1||x>n||y<1||y>m)return 1;
return 0;
}
int main()
{
int i,j,x,y,l,s,t,k,cs=0,vx,vy;
while(~scanf("%d%d",&n,&m)&&(n+m))
{
cs++;
init();
vx=vy=0;
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
scanf("%d",&g[i][j]);
if((i+j)%2)jiou[i][j]=++vx; //奇偶染色
else jiou[i][j]=++vy;
}
}
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
if(g[i][j]!=-1){
l=0; k=g[i][j];
while(k){
if(k%2){
x=i+d[l][0]; y=j+d[l][1];
if(g[x][y]!=-1&&!yj(x,y)){
s=jiou[i][j]; t=jiou[x][y];
if((i+j)%2==0)swap(s,t);
add(s,t);
}
}
k=k/2;
l++;
}
}
}
}
n=max(vx,vy);
n=erfenpipei();
printf("%d. %d\n",cs,n);
}
return 0;
}
方法二:
图中所有的点为1~n*m,将其拆成两份,为每一对看守关系建立双边,求出最大匹配/2。
代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <queue>
using namespace std;
const int maxn=2505;
const int maxm=1000005;
struct EdgeNode
{
int to;
int next;
}edge[maxm];
int head[maxn],cnt;
void add(int x,int y)
{
edge[cnt].to=y;
edge[cnt].next=head[x];
head[x]=cnt++;
}
int n,m,v[maxn],pre[maxn];
int d[15][3]={{-1,-2},{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,0},{0,1},{1,0},{0,-1}};
int g[maxn][maxn];
void init()
{
cnt=0;
memset(head,-1,sizeof(head));
}
int dfs(int x)
{
int y;
for(int i=head[x];i!=-1;i=edge[i].next)
{
y=edge[i].to;
if(!v[y]){
v[y]=1;
if(!pre[y]||dfs(pre[y])){
pre[y]=x;
return true;
}
}
}
return false;
}
int erfenpipei()
{
int sum=0;
memset(pre,0,sizeof(pre));
for(int i=1;i<=n;i++){
memset(v,0,sizeof(v));
if(dfs(i))
sum++;
}
return sum;
}
int yj(int x,int y)
{
if(x<1||x>n||y<1||y>m)return 1;
return 0;
}
int main()
{
int i,j,x,y,l,s,t,k,cs=0;
while(~scanf("%d%d",&n,&m)&&(n+m))
{
cs++;
init();
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
scanf("%d",&g[i][j]);
}
}
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
if(g[i][j]!=-1){
l=0; k=g[i][j];
while(k){
if(k%2){
x=i+d[l][0]; y=j+d[l][1];
if(g[x][y]!=-1&&!yj(x,y)){
s=(i-1)*m+j; t=(x-1)*m+y;
add(s,t);
add(t,s);
}
}
k=k/2;
l++;
}
}
}
}
n=n*m;
n=erfenpipei()/2;
printf("%d. %d\n",cs,n);
}
return 0;
}
图中的点根据(i+j)%2为奇数或者偶数,划分为二分图,然后建图,直接求出二分最大匹配。
代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <queue>
using namespace std;
const int maxn=2505;
const int maxm=1000005;
struct EdgeNode
{
int to;
int next;
}edge[maxm];
int head[maxn],cnt;
void add(int x,int y)
{
edge[cnt].to=y;
edge[cnt].next=head[x];
head[x]=cnt++;
}
int n,m,v[maxn],pre[maxn];
int d[15][3]={{-1,-2},{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,0},{0,1},{1,0},{0,-1}};
int g[maxn][maxn],jiou[maxn][maxn];
void init()
{
cnt=0;
memset(head,-1,sizeof(head));
}
int dfs(int x)
{
int y;
for(int i=head[x];i!=-1;i=edge[i].next)
{
y=edge[i].to;
if(!v[y]){
v[y]=1;
if(!pre[y]||dfs(pre[y])){
pre[y]=x;
return true;
}
}
}
return false;
}
int erfenpipei()
{
int sum=0;
memset(pre,0,sizeof(pre));
for(int i=1;i<=n;i++){
memset(v,0,sizeof(v));
if(dfs(i))
sum++;
}
return sum;
}
int yj(int x,int y)
{
if(x<1||x>n||y<1||y>m)return 1;
return 0;
}
int main()
{
int i,j,x,y,l,s,t,k,cs=0,vx,vy;
while(~scanf("%d%d",&n,&m)&&(n+m))
{
cs++;
init();
vx=vy=0;
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
scanf("%d",&g[i][j]);
if((i+j)%2)jiou[i][j]=++vx; //奇偶染色
else jiou[i][j]=++vy;
}
}
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
if(g[i][j]!=-1){
l=0; k=g[i][j];
while(k){
if(k%2){
x=i+d[l][0]; y=j+d[l][1];
if(g[x][y]!=-1&&!yj(x,y)){
s=jiou[i][j]; t=jiou[x][y];
if((i+j)%2==0)swap(s,t);
add(s,t);
}
}
k=k/2;
l++;
}
}
}
}
n=max(vx,vy);
n=erfenpipei();
printf("%d. %d\n",cs,n);
}
return 0;
}
方法二:
图中所有的点为1~n*m,将其拆成两份,为每一对看守关系建立双边,求出最大匹配/2。
代码:
#include <iostream>
#include <string.h>
#include <stdio.h>
#include <queue>
using namespace std;
const int maxn=2505;
const int maxm=1000005;
struct EdgeNode
{
int to;
int next;
}edge[maxm];
int head[maxn],cnt;
void add(int x,int y)
{
edge[cnt].to=y;
edge[cnt].next=head[x];
head[x]=cnt++;
}
int n,m,v[maxn],pre[maxn];
int d[15][3]={{-1,-2},{-2,-1},{-2,1},{-1,2},{1,2},{2,1},{2,-1},{1,-2},{-1,0},{0,1},{1,0},{0,-1}};
int g[maxn][maxn];
void init()
{
cnt=0;
memset(head,-1,sizeof(head));
}
int dfs(int x)
{
int y;
for(int i=head[x];i!=-1;i=edge[i].next)
{
y=edge[i].to;
if(!v[y]){
v[y]=1;
if(!pre[y]||dfs(pre[y])){
pre[y]=x;
return true;
}
}
}
return false;
}
int erfenpipei()
{
int sum=0;
memset(pre,0,sizeof(pre));
for(int i=1;i<=n;i++){
memset(v,0,sizeof(v));
if(dfs(i))
sum++;
}
return sum;
}
int yj(int x,int y)
{
if(x<1||x>n||y<1||y>m)return 1;
return 0;
}
int main()
{
int i,j,x,y,l,s,t,k,cs=0;
while(~scanf("%d%d",&n,&m)&&(n+m))
{
cs++;
init();
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
scanf("%d",&g[i][j]);
}
}
for(i=1;i<=n;i++){
for(j=1;j<=m;j++){
if(g[i][j]!=-1){
l=0; k=g[i][j];
while(k){
if(k%2){
x=i+d[l][0]; y=j+d[l][1];
if(g[x][y]!=-1&&!yj(x,y)){
s=(i-1)*m+j; t=(x-1)*m+y;
add(s,t);
add(t,s);
}
}
k=k/2;
l++;
}
}
}
}
n=n*m;
n=erfenpipei()/2;
printf("%d. %d\n",cs,n);
}
return 0;
}
相关文章推荐
- HDU 1533 Going Home 最小费用最大流(入门)(模板)或者 二分匹配
- HDU 4618 Palindrome Sub-Array 二分(奇偶)+hash判断是否对称
- hdu 5313 Bipartite Graph(dfs染色 或者 并查集)
- hdu 5493 Queue 树状数组第K大或者二分
- HDU 2141 哈希表或者二分
- HDU 4024 Dwarven Sniper’s hunting(数学公式 或者是二分)
- hdu 2444 The Accomodation of Students【二分图染色+最大二分匹配数】
- HDU 3360 National Treasures 奇偶匹配的最低点覆盖
- hdu 5289 Assignment(2015多校第一场第2题)RMQ+二分(或者multiset模拟过程)
- hdu3360+二分匹配(匈牙利算法)
- HDU 1045 fire net【二分匹配或者DFS】
- HDU 3360 National Treasures 奇偶匹配最小点覆盖
- HDU 3360-National Treasures(最小点覆盖+奇偶匹配)
- hdu 2444 The Accomodation of Students (二分染色)
- hdu 3360 National Treasures 二分行列匹配
- HDU 3360 National Treasures(二分匹配,最小点覆盖)
- hdu 2444 The Accomodation of Students (交叉染色+二分匹配)
- ★HDU 3605 网络流+缩图 或者二分多重匹配
- HDU 2899 (二分 或者 三分)
- hdu3360+二分匹配(匈牙利算法)