[TCO2013]DirectionBoard
题意:给一个网格,每个格子有一个方向表示在这个格子上要往哪个方向走,你可以改变某些格子的方向,问最少多少次操作使得从任意格子出发都能回到这个格子
woc这都不会我还是回家种田去吧...
题目的要求是改变某些点的出边使得整个图变成许多环,注意到在满足要求的图中,每个点只有一条入边和一条出边,所以我们对每个格子建两个点代表它的出边和入边,相当于是要找到一组入边和出边的匹配,如果一个入边和出边匹配是原来的方向,那么费用为$0$,否则费用为$1$,跑最小费用最大流即可
#include<stdio.h> #include<string> #include<vector> #include<queue> #include<string.h> using namespace std; const int inf=2147483647; int h[510],nex[3010],to[3010],cap[3010],cos[3010],M=1,S,T; void ins(int a,int b,int c,int d){ M++; to[M]=b; cap[M]=c; cos[M]=d; nex[M]=h[a]; h[a]=M; } void add(int a,int b,int c,int d){ ins(a,b,c,d); ins(b,a,0,-d); } int dis[510],n,sum,cost; bool aug[510]; struct pr{ int x,d; pr(int u=0){x=u;d=dis[u];} }t; bool operator<(pr a,pr b){return a.d>b.d;} priority_queue<pr>q; bool bfs(){ int x,i; memset(dis,63,sizeof(dis)); dis[T]=0; q.push(T); while(!q.empty()){ t=q.top(); q.pop(); x=t.x; if(dis[x]!=t.d)continue; for(i=h[x];i;i=nex[i]){ if(cap[i^1]&&dis[x]-cos[i]<dis[to[i]]){ dis[to[i]]=dis[x]-cos[i]; q.push(to[i]); } } } sum+=dis[S]; for(x=1;x<=n;x++){ for(i=h[x];i;i=nex[i])cos[i]+=dis[to[i]]-dis[x]; } return dis[S]!=dis[0]; } int dfs(int x,int f){ if(f==0)return 0; if(x==T){ cost+=f*sum; return f; } int us=0,i,t; aug[x]=1; for(i=h[x];i;i=nex[i]){ if(!cos[i]&&cap[i]&&!aug[to[i]]){ t=dfs(to[i],min(cap[i],f-us)); cap[i]-=t; cap[i^1]+=t; us+=t; if(us==f)break; } } if(us==f)aug[x]=0; return us; } int costflow(){ do{ do{ memset(aug,0,sizeof(aug)); }while(dfs(S,inf)); }while(bfs()); return cost; } const int g[4][2]={{0,-1},{0,1},{-1,0},{1,0}}; int type(char c){ if(c=='L')return 0; if(c=='R')return 1; if(c=='U')return 2; return 3; } class DirectionBoard{ public: int getMinimum(vector<string>mp){ int n,m,i,j,k,x,y,t; n=mp.size(); m=mp[0].length(); S=n*m*2+1; T=S+1; ::n=T; for(i=0;i<n;i++){ for(j=0;j<m;j++){ add(S,i*m+j+1,1,0); t=type(mp[i][j]); for(k=0;k<4;k++){ x=(i+g[k][0]+n)%n; y=(j+g[k][1]+m)%m; add(i*m+j+1,x*m+y+1+n*m,1,k!=t); } add(i*m+j+1+n*m,T,1,0); } } return costflow(); } }; /* int main(){ vector<string>vt; char s[20]; DirectionBoard cl; while(~scanf("%s",s))vt.push_back(s); printf("%d",cl.getMinimum(vt)); } */
[TCO2013]DirectionBoard的更多相关文章
- [TCO2013]TrickyInequality
$\newcommand{stirf}[2]{{{#1}\brack{#2}}}$$\newcommand{stirs}[2]{{{#1}\brace{#2}}}$题意:$\sum\limits_{i ...
- [TCO2013]Block3Checkers
题意:一个网格上有一些障碍和$3$个在网格边界上的棋子,你要添加一些障碍使得没有两个棋子四连通,问最少添加多少个障碍 官方题解——一张图教你做人... 三个棋子将网格边界分成三段,添加障碍后网格中一定 ...
- [TCO2013]LitPanels
题意:一个$n\times m$的无色网格,你可以在其中选择两个$x\times y$的子矩形并在其中将其中任意的格子涂上颜色,问最终能得到多少种不同的网格 做这题会用到一个概念叫包围盒(boundi ...
随机推荐
- bzoj 2165 DP
首先如果不考虑数据范围的话,因为每一层都是等效的,所以我们可以用w[i][j][k]来表示在某一层的j位置,称作i次电梯到k位置,最多上升多少层,那么我们可以比较容易的写出转移,因为m十分大,i可能与 ...
- position的用法与心得
position的四个属性值: relative absolute fixed static 为了便于理解,首先创建对应的div <div class="main"> ...
- spring-retry 重试机制
业务场景 应用中需要实现一个功能: 需要将数据上传到远程存储服务,同时在返回处理成功情况下做其他操作.这个功能不复杂,分为两个步骤:第一步调用远程的Rest服务逻辑包装给处理方法返回处理结果:第二步拿 ...
- js/jq 键盘上下左右回车按键
js判断上下左右回车按键: document.onkeydown=function(e){ e=window.event||e; switch(e.keyCode){ case 37: //左键 co ...
- 关于EditText.setText()无法显示的问题
将EditText在初始化后调用EditText.setSaveEnabled(false); 让Android 系统不保存值,这样就不会恢复了.
- [Leetcode Week15]Populating Next Right Pointers in Each Node
Populating Next Right Pointers in Each Node 题解 原创文章,拒绝转载 题目来源:https://leetcode.com/problems/populati ...
- Linux时间子系统之八:动态时钟框架(CONFIG_NO_HZ、tickless)【转】
转自:http://blog.csdn.net/droidphone/article/details/8112948 版权声明:本文为博主原创文章,未经博主允许不得转载. 目录(?)[-] 数据结 ...
- quazip 在windows msvc 2005 下的编译
quazip 在windows msvc 2005 下的编译 http://blog.csdn.net/v6543210/article/details/11661427
- OC 06 Block、数组高级
主要内容: ⼀.Block语法 ⼆.Block使⽤ 三.Block实现数组排序 Block简介 Block:块语法,本质上是匿名函数(没有名称的函数) 标准C⾥面没有Block,C语⾔言的后期扩展版本 ...
- 升级OS10.11系统后 Xcode6.4的变化少了个按钮 could not launch “Xcode” Xcode 插件安装
升级OS10.11系统后 Xcode6.4的变化少了个按钮 could not launch “Xcode” Xcode 插件安装 A: 升级10.11后Xcode 左上角模拟器选择菜单不在了 ...