[费用流]BZOJ:3171: [Tjoi2013]循环格
2014-02-28 10:58
239 查看
3171: [Tjoi2013]循环格
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 258 Solved: 153
[Submit][Status]
Description
Input
第一行两个整数R,C。表示行和列,接下来R行,每行C个字符LRUD,表示左右上下。
Output
一个整数,表示最少需要修改多少个元素使得给定的循环格完美
Sample Input
3 4RRRD
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; }
相关文章推荐
- Lync server 2013 监控角色的安装
- 实现电话自动拨打、挂断
- 关于java里面Collection包括List,Map等初始化内部匿名类和泛型的一个例子
- 第一章 开始
- Linux 进程间通信 (IPC) // 消息队列
- mongodb管理工具 rockmongo使用时出现的问题
- linux和window文件传输利器rzsz
- 终端播放器moc配置解决乱码问题
- iOS高级进阶(3)Core Text入门
- 在WIN8.1 正式版上运行VC++6.0的方法
- 怎样将文件夹里的文件名保存到文本文档
- 一步一步写算法(之递归和堆栈)(转)
- Outlook 开发
- Linux 进程间通信 (IPC) //共享内存
- SCCM2012R2部署之二:先决条件
- JBoss Entity Bean Demo
- 开源软件七大盈利模式
- The Function Pointer Tutorials
- php curl详解用法[真的详解]
- C语言接口与实现创建可重用软件的技术读书笔记(2)---接口与实现