[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 ...
随机推荐
- 【CC2530入门教程-01】CC2530微控制器开发入门基础
[引言] 本系列教程就有关CC2530单片机应用入门基础的实训案例进行分析,主要包括以下6部分的内容:[1]CC2530微控制器开发入门基础.[2]通用I/O端口的输入和输出.[3]外部中断初步应用. ...
- hdu 2717 Catch That Cow(广搜bfs)
题目链接:http://i.cnblogs.com/EditPosts.aspx?opt=1 Catch That Cow Time Limit: 5000/2000 MS (Java/Others) ...
- Android 聊天软件客户端
1.代码架构图 2.qq.model层 3.qq.app层 4.qq.Constatnt层 5.qq.util层 6.qq.broadcast层 7.qq.control层 8.qq.view层 9. ...
- C++学习之路(五):复制构造函数与赋值运算符重载
之前没有细想过两者的区别,今天对此进行简要记录,后续完善补充. 复制构造函数是在类对象被创建时调用的,但是赋值运算符是被已经存在的对象调用完成赋值操作. 复制构造函数只在对象实例化时才被调用,即在复制 ...
- [device tree] How to decompile a compiled .dtb (device tree blog) into .dts (device tree source).
$ ./out/target/product/project_name/obj/KERNEL_OBJ/scripts/dtc/dtc -I dtb -O dts -o decompiled.dts ~ ...
- 2017多校第6场 HDU 6105 Gameia 博弈
题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=6105 题意:Alice和Bob玩一个游戏,喷漆!现在有一棵树上边的节点最开始都没有被染色.游戏规则是: ...
- oc 与 swift 之间的桥接文件 (ProjectNmae-Bridging-Header.h) (ProjectNmae-Swift.h)
oc 与 Swift 是2种不同的语言, oc代码只能写带oc文件里, Swift代码只能写在Swift文件里, 虽然2者不同语言, 但却能互相调用, 不过需要进行一下桥接, 就是下面的2个文件 (P ...
- RSA加密解密与加签验签
RSA公钥加密算法是1977年由罗纳德·李维斯特(Ron Rivest).阿迪·萨莫尔(Adi Shamir)和伦纳德·阿德曼(Leonard Adleman)一起提出的.1987年7月首次在美国公布 ...
- jquery文档加载几种写法,图片加载写法
jquery文档加载写法: $(function(){ }) ; //个人最常使用方式 $(document).ready(function(){ }); //调用文档对象下的ready方法传入一个函 ...
- _stdcall调用
以前看windows编程时一直有个 _stdcall 函数调用约定 一直不是很理解,只能硬记. 现在终于在<程序是怎样跑起来的>这本书书中找到了答案. 1. _stdcall 是stand ...