[费用流]BZOJ:3171: [Tjoi2013]循环格

来源:互联网 发布:网络电视怎么看直播 编辑:程序博客网 时间:2024/05/17 06:39

3171: [Tjoi2013]循环格

Time Limit: 1 Sec  Memory Limit: 128 MB
Submit: 258  Solved: 153
[Submit][Status]

Description

Input

第一行两个整数R,C。表示行和列,接下来R行,每行C个字符LRUD,表示左右上下。

Output

 

一个整数,表示最少需要修改多少个元素使得给定的循环格完美

Sample Input

3 4
RRRD
URLL
LRRR

Sample Output

2

HINT

1<=R,L<=15

Source

首先,我们可以推断出来:构成循环格的条件是每个格子入度出度都是1
那么我们可以构造一个类似二分图的图,左边右边点相同,如果i可以指到j,左i到右j连一条边
这样每个格子都有一个入边和出边了
然后是费用的问题,如果存在边(左i,右j)如果i原本就指向j,则cost[i][j]=0,否则为1
然后求最小费用最大流
/**************************************************************    Problem: 3171    User: SKYDEC    Language: C++    Result: Accepted    Time:268 ms    Memory:4712 kb****************************************************************/ #include<stdio.h>#define f(i,j) ((i)-1)*c+(j)#define debug printf("yeah!")using namespace std;bool create[800][800];long cost[800][800];long pre[500];long r,c,s,t;long que[100000],k[100000];int spfa(){    pre[t]=-1;bool gone[500]={false};que[0]=1;que[1]=s;gone[s]=true;long dis[800];for(long i=s;i<=t;i++)dis[i]=2100000000;    dis[0]=0;    while(que[0]!=0)    {        k[0]=0;        for(long i=1;i<=que[0];i++)        {            long cur=que[i];            for(long j=s;j<=t;j++)            if(create[cur][j]&&(dis[cur]+cost[cur][j]<dis[j]))            {                dis[j]=dis[cur]+cost[cur][j];pre[j]=cur;                if(!gone[j]){k[++k[0]]=j;gone[j]=true;}            }            gone[cur]=false;        }        que[0]=k[0];for(long u=1;u<=que[0];u++)que[u]=k[u];    }    return pre[t];}int main(){    //freopen("grid.in","r",stdin);freopen("grid.out","w",stdout);    scanf("%ld%ld",&r,&c);s=0;t=2*r*c+1;char goe;scanf("%c",&goe);    for(long i=1;i<=r;i++)for(long j=1;j<=c;j++)    {        create[s][f(i,j)]=true;create[f(i,j)+r*c][t]=true;        create[f(i,j)][f(i,j%c+1)+r*c]=true;cost[f(i,j)][f(i,j%c+1)+r*c]=1;cost[f(i,j%c+1)+r*c][f(i,j)]=-1;        create[f(i,j)][f(i%r+1,j)+r*c]=true;cost[f(i,j)][f(i%r+1,j)+r*c]=1;cost[f(i%r+1,j)+r*c][f(i,j)]=-1;        long ti=i,tj=j;if(i==1)ti=r;else ti--;        create[f(i,j)][f(ti,tj)+r*c]=true;cost[f(i,j)][f(ti,tj)+r*c]=1;cost[f(ti,tj)+r*c][f(i,j)]=-1;        ti=i;tj=j;if(j==1)tj=c;else tj--;        create[f(i,j)][f(ti,tj)+r*c]=true;cost[f(i,j)][f(ti,tj)+r*c]=1;cost[f(ti,tj)+r*c][f(i,j)]=-1;    }    for(long i=1;i<=r;i++)    {        for(long j=1;j<=c;j++)        {            char u;scanf("%c",&u);            if(u=='R')cost[f(i,j)][f(i,j%c+1)+r*c]=cost[f(i,j%c+1)+r*c][f(i,j)]=0;            if(u=='D')cost[f(i,j)][f(i%r+1,j)+r*c]=cost[f(i%r+1,j)+r*c][f(i,j)]=0;            if(u=='U')            {                long ti=i,tj=j;if(i==1)ti=r;else ti--;                cost[f(i,j)][f(ti,tj)+r*c]=cost[f(ti,tj)+r*c][f(i,j)]=0;            }            if(u=='L')            {                long ti=i,tj=j;if(j==1)tj=c;else tj--;                cost[f(i,j)][f(ti,tj)+r*c]=cost[f(ti,tj)+r*c][f(i,j)]=0;            }        }        while(true)        {            scanf("%c",&goe);            if(goe=='\n')break;        }    }    long long ans=0;    while(spfa()!=-1)    {        long p=t;        while(p!=s)        {            ans+=cost[pre[p]][p];            create[pre[p]][p]=false;            create[p][pre[p]]=true;            p=pre[p];        }    }    printf("%lld",ans);    //for(;;);    return 0;}




0 0