bzoj1443: [JSOI2009]游戏Game

二分图博弈了解下?

感觉自己匈牙利很扎实,居然没有wa过

先是码了个O(n^2m)的(这里的n,m是点数和边数),就是每枚举到一个最大匹配里面的点,就删这个点重跑一次最大匹配

后来发现其实直接让这个点所匹配的点去找另一个就行了。(好像跑的挺慢。。)

网上好像都是网络流?不会啊还是自己yy匈牙利

/*#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const int dx[4]={-1,0,1,0};
const int dy[4]={0,1,0,-1};

struct node
{
    int x,y,next;
}a[41000];int len,last[11000];
void ins(int x,int y)
{
    len++;
    a[len].x=x;a[len].y=y;
    a[len].next=last[x];last[x]=len;
}
int zx,zy,ys[110][110];
struct point
{
    int x,y;
}px[11000],py[11000];

//-------init--------------- 

int del,wi;bool xin[11000],yin[11000];
int match[11000];
int tim,chw[11000];
bool findmuniu(int x)
{
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(wi==2&&del==y)continue;
        if(chw[y]!=tim)
        {
            chw[y]=tim;
            if(match[y]==0||findmuniu(match[y])==true)
            {
                if(del==0)yin[y]=true;
                match[y]=x;
                return true;
            }
        }
    }
    return false;
}
int gomatch()
{
    tim=0;
    memset(match,0,sizeof(match));
    memset(chw,0,sizeof(chw));
    if(del==0) 
    {
        memset(xin,false,sizeof(xin));
        memset(yin,false,sizeof(yin));
    }
    int ret=0;
    for(int i=1;i<=zx;i++)
    {
        if(wi==1&&i==del)continue;
        tim++;
        if(findmuniu(i)==true)
        {
            ret++;
            if(del==0)xin[i]=true;
        }
    }
    return ret;
}

//----------------match-----------------

point as[11000];int aslen;
bool cmp(point p1,point p2){return (p1.x==p2.x)?(p1.y<p2.y):(p1.x<p2.x);}
char ss[110];
int main()
{
    freopen("game.in","r",stdin);
    freopen("game.out","w",stdout);
    
    int n,m;
    scanf("%d%d",&n,&m);
    zx=0;zy=0;memset(ys,-1,sizeof(ys));
    for(int i=1;i<=n;i++)
    {
        scanf("%s",ss+1);
        for(int j=1;j<=m;j++)
            if(ss[j]=='.')
            {
                if((i+j)%2==0)ys[i][j]=++zx,px[zx].x=i,px[zx].y=j;
                else           ys[i][j]=++zy,py[zy].x=i,py[zy].y=j;
            }
    }
    len=0;memset(last,0,sizeof(last));
    for(int i=1;i<=n;i++)
        for(int j=(i%2==1?1:2);j<=m;j+=2)
            if(ys[i][j]!=-1)
                for(int k=0;k<=3;k++)
                {
                    int ti=i+dx[k],tj=j+dy[k];
                    if(ti>0&&ti<=n&&tj>0&&tj<=m&&ys[ti][tj]!=-1)
                        ins(ys[i][j],ys[ti][tj]);
                }
    //--------composition---------
    
    del=0;wi=0;
    int mmax=gomatch();
    aslen=0;
    for(int i=1;i<=zx;i++)
    {
        if(xin[i]==false)as[++aslen]=px[i];
        else
        {
            del=i;wi=1;
            if(mmax==gomatch())as[++aslen]=px[i];
        }
    }
    for(int i=1;i<=zy;i++)
    {
        if(yin[i]==false)as[++aslen]=py[i];
        else
        {
            del=i;wi=2;
            if(mmax==gomatch())as[++aslen]=py[i];
        }
    }
    
    if(aslen==0)printf("LOSE
");
    else
    {
        printf("WIN
");
        sort(as+1,as+aslen+1,cmp);
        for(int i=1;i<=aslen;i++)printf("%d %d
",as[i].x,as[i].y);
    }
    return 0;
}*/
#include<cstdio>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<cmath>
using namespace std;
const int dx[4]={-1,0,1,0};
const int dy[4]={0,1,0,-1};

struct node
{
    int x,y,next;
}a[41000];int len,last[11000];
void ins(int x,int y)
{
    len++;
    a[len].x=x;a[len].y=y;
    a[len].next=last[x];last[x]=len;
}
int z,tp,ys[110][110];
struct point
{
    int x,y;
}p[11000];

//-------init--------------- 

bool in[11000];
int match[11000];
int tim,chw[11000];
bool findmuniu(int x)
{
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(chw[y]!=tim)
        {
            chw[y]=tim;
            if(match[y]==0||findmuniu(match[y])==true)
            {
                in[y]=true;
                match[y]=x;
                match[x]=y;
                return true;
            }
        }
    }
    return false;
}
int gomatch()
{
    tim=0;
    memset(match,0,sizeof(match));
    memset(chw,0,sizeof(chw));
    memset(in,false,sizeof(in));
    int ret=0;
    for(int i=1;i<=tp;i++)
    {
        tim++;
        if(findmuniu(i)==true){ret++;in[i]=true;}
    }
    return ret;
}

bool findanother(int x)
{
    for(int k=last[x];k;k=a[k].next)
    {
        int y=a[k].y;
        if(chw[y]!=tim&&y!=match[x])
        {
            chw[y]=tim;
            if(match[y]==0||findanother(match[y])==true)
                return true; 
        }
    }
    return false;
}

//----------------match-----------------

point as[11000];int aslen;
bool cmp(point p1,point p2){return (p1.x==p2.x)?(p1.y<p2.y):(p1.x<p2.x);}
char ss[110][110];
int main()
{
    freopen("game.in","r",stdin);
    freopen("game.out","w",stdout);
    int n,m;
    scanf("%d%d",&n,&m);
    z=0;memset(ys,-1,sizeof(ys));
    for(int i=1;i<=n;i++)scanf("%s",ss[i]+1);
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(ss[i][j]=='.')
                if((i+j)%2==0)ys[i][j]=++z,p[z].x=i,p[z].y=j;
    tp=z;
    for(int i=1;i<=n;i++)
        for(int j=1;j<=m;j++)
            if(ss[i][j]=='.')
                if((i+j)%2==1)ys[i][j]=++z,p[z].x=i,p[z].y=j;
                
    len=0;memset(last,0,sizeof(last));
    for(int i=1;i<=n;i++)
        for(int j=(i%2==1?1:2);j<=m;j+=2)
            if(ys[i][j]!=-1)
                for(int k=0;k<=3;k++)
                {
                    int ti=i+dx[k],tj=j+dy[k];
                    if(ti>0&&ti<=n&&tj>0&&tj<=m&&ys[ti][tj]!=-1)
                        ins(ys[i][j],ys[ti][tj]), ins(ys[ti][tj],ys[i][j]);
                }
    //--------composition---------
    
    int mmax=gomatch();
    aslen=0;
    for(int i=1;i<=z;i++)
    {
        if(in[i]==false)as[++aslen]=p[i];
        else
        {
            tim++;
            if(findanother(match[i])==true)as[++aslen]=p[i];
        }
    }
    
    if(aslen==0)printf("LOSE
");
    else
    {
        printf("WIN
");
        sort(as+1,as+aslen+1,cmp);
        for(int i=1;i<=aslen;i++)printf("%d %d
",as[i].x,as[i].y);
    }
    return 0;
}
原文地址:https://www.cnblogs.com/AKCqhzdy/p/8907539.html