不难发现,每个点出度显然为1,要想整个图形成环,必然每个点的入度也为1;

所以,不难想到将每个点i拆成两个点i1,i2构成二分图,

连边s--->i1 流量为1,费用为0,i2--->t流量为1,费用为0

这样左右两边的点都只能匹配1次,也就满足了出入度为1;

对于点i的上下左右4个点,分别连i1--->j2,容量为1;

对于点i原来指向的点,之间边的费用为0,否则费用为1,表示要修改1次

然后最小费用最大流即可

注意这道题最左边的点超出边界后自动到达最右边的点

  1. const inf=;
  2.       dx:array[..] of integer=(-,,,);
  3.       dy:array[..] of integer=(,,-,);
  4.  
  5. type node=record
  6.        flow,cost,point,next:longint;
  7.      end;
  8.  
  9. var edge:array[..] of node;
  10.     p,cur,pre,d:array[..] of longint;
  11.     q:array[..] of longint;
  12.     v:array[..] of boolean;
  13.     num,kind:array[..,..] of longint;
  14.     len,x,y,i,j,n,m,h,c,k,t:longint;
  15.     s:string;
  16.  
  17. procedure add(x,y,f,c:longint);
  18.   begin
  19.     inc(len);
  20.     edge[len].point:=y;
  21.     edge[len].flow:=f;
  22.     edge[len].cost:=c;
  23.     edge[len].next:=p[x];
  24.     p[x]:=len;
  25.   end;
  26.  
  27. function spfa:boolean;
  28.   var f,r,x,y:longint;
  29.   begin
  30.     q[]:=;
  31.     f:=;
  32.     r:=;
  33.     for i:= to t do
  34.       d[i]:=inf;
  35.     d[]:=;
  36.     fillchar(v,sizeof(v),false);
  37.     v[]:=true;
  38.     while f<=r do
  39.     begin
  40.       x:=q[f];
  41.       v[x]:=false;
  42.       i:=p[x];
  43.       while i<>- do
  44.       begin
  45.         y:=edge[i].point;
  46.         if edge[i].flow> then
  47.         begin
  48.           if d[x]+edge[i].cost<d[y] then
  49.           begin
  50.             d[y]:=edge[i].cost+d[x];
  51.             pre[y]:=x;
  52.             cur[y]:=i;
  53.             if not v[y] then
  54.             begin
  55.               v[y]:=true;
  56.               inc(r);
  57.               q[r]:=y;
  58.             end;
  59.           end;
  60.         end;
  61.         i:=edge[i].next;
  62.       end;
  63.       inc(f);
  64.     end;
  65.     if d[t]=inf then exit(false) else exit(true);
  66.   end;
  67.  
  68. function mincost:longint;
  69.   var i,j:longint;
  70.   begin
  71.     mincost:=;
  72.     while spfa do
  73.     begin
  74.       i:=t;
  75.       while i<> do
  76.       begin
  77.         j:=cur[i];
  78.         dec(edge[j].flow);
  79.         inc(edge[j xor ].flow);
  80.         i:=pre[i];
  81.       end;
  82.       mincost:=mincost+d[t];
  83.     end;
  84.   end;
  85.  
  86. begin
  87.   len:=-;
  88.   fillchar(p,sizeof(p),);
  89.   readln(n,m);
  90.   for i:= to n do
  91.   begin
  92.     readln(s);
  93.     for j:= to m do
  94.     begin
  95.       inc(h);
  96.       num[i,j]:=h;
  97.       if s[j]='U' then kind[i,j]:=;
  98.       if s[j]='D' then kind[i,j]:=;
  99.       if s[j]='L' then kind[i,j]:=;
  100.       if s[j]='R' then kind[i,j]:=;
  101.     end;
  102.   end;
  103.   t:=n*m*+;
  104.   for i:= to n do
  105.   begin
  106.     for j:= to m do
  107.     begin
  108.       add(,num[i,j],,);
  109.       add(num[i,j],,,);
  110.       add(num[i,j]+h,t,,);
  111.       add(t,num[i,j]+h,,);
  112.       for k:= to do
  113.       begin
  114.         x:=i+dx[k];
  115.         y:=j+dy[k];
  116.         if x= then x:=n;
  117.         if x=n+ then x:=;
  118.         if y= then y:=m;
  119.         if y=m+ then y:=;
  120.         if kind[i,j]=k then c:= else c:=;
  121.         add(num[i,j],num[x,y]+h,inf,c);
  122.         add(num[x,y]+h,num[i,j],,-c);
  123.       end;
  124.     end;
  125.   end;
  126.   writeln(mincost);
  127. end.

bzoj3171的更多相关文章

  1. BZOJ3171 Tjoi2013 循环格

    传送门 Description 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0).给定一个起始位置(r,c) ,你可以沿着箭头 ...

  2. [TJOI2013]循环格 费用流 BZOJ3171

    题目背景 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0).给定一个起始位(r,c),你可以沿着箭头方向在格子间行走.即:如果 ...

  3. bzoj3171: [Tjoi2013]循环格(费用流)

    传送门 其实这题的建图并不难(虽然我并没有想出来) 首先,每一个点的入度和出度必须为$1$ 那么我们考虑拆点 每个点的出度点向它能到达的点的入度点连边,容量$1$,如果方向为原来的方向则费用$0$否则 ...

  4. 【BZOJ3171】[TJOI2013] 循环格(网络流)

    点此看题面 大致题意: 给你一个循环格,每个格子有一个方向.问你至少修改多少格子,才能使从每个格子出发都能回到原格子. 建图 这是道网络流题目,主要就是考虑如何建图. 我们可以把每个点拆成两个点,一个 ...

  5. 【bzoj3171】[Tjoi2013]循环格

    题目描述: 一个循环格就是一个矩阵,其中所有元素为箭头,指向相邻四个格子.每个元素有一个坐标(行,列),其中左上角元素坐标为(0,0).给定一个起始位置(r,c) ,你可以沿着箭头防线在格子间行走.即 ...

  6. [bzoj3171]循环格

    如果把这个矩阵看成一张图,题目相当于要求每一个点的入度和出度都是1(也就是有很多环),否则指向环的点就无法走回自己了将所有点拆成两个,S向原来的点流(1,0)的边,拆出来的点向T连(1,0)的边,然后 ...

  7. [转载]hzwer的bzoj题单

    counter: 664BZOJ1601 BZOJ1003 BZOJ1002 BZOJ1192 BZOJ1303 BZOJ1270 BZOJ3039 BZOJ1191 BZOJ1059 BZOJ120 ...

  8. Topcoder SRM570 D1L3 CurvyonRails

    几个样例: 5 5wCCwwwCC....w......www..wReturns: 0 3 3C.w....C.Returns: 1 21 20CC..CCCw.CwC..CC.w.CC.CCCwC ...

  9. 网络流专题练习Day2

    04/17  目前做了:题 由于目前六道都是1A感觉非常爽... BZOJ1412: [ZJOI2009]狼和羊的故事 “狼爱上羊啊爱的疯狂,谁让他们真爱了一场:狼爱上羊啊并不荒唐,他们说有爱就有方向 ...

随机推荐

  1. spring mvc 全局异常处理

    package com.tool; public class MyException extends Exception{ public String Msg; public String ErrCo ...

  2. flexbox布局模式-- 浅谈

    简介 Flexbox,一种CSS3的布局模式,也叫做弹性盒子模型,用来为盒装模型提供最大的灵活性.今天主要从以下几个方面简单谈谈flex. 1 版本更迭 2 flex容器 3 flex项目 4 fle ...

  3. C++ txt文档读取

    void readfile(string filepath){ ifstream myfile; if (!myfile) { cout << "打开文件出错!"; e ...

  4. C++成员变量初始化顺序问题

    由于面试题中,考官出了一道简单的程序输出结果值的题:如下, class A { private: int n1; int n2; public: A():n2(0),n1(n2+2){} void P ...

  5. 暑假集训(3)第一弹 -----还是畅通工程(hdu1233)

    题意梗概:N(n<100)个村子想要富起来,自然就要先修路,不过到底还是没富起来,所以陷入了一个怪圈 :资金不足->修不起路->资金不足...... 为了实现走向全民小康社会,全面实 ...

  6. Cannot connect to (local) sql server 2008

    Make following steps to solve the issue: Cannot connect to (local). ADDITIONAL INFORMATION: Login fa ...

  7. OpenJudge/Poj 1458 Common Subsequence

    1.链接地址: http://poj.org/problem?id=1458 http://bailian.openjudge.cn/practice/1458/ 2.题目: Common Subse ...

  8. Eclipse配置CAS server

    1.下载cas server的源码包(我使用的是cas-server-3.5.2.1-release.zip) 2.解压压缩包到某个目录下,找到cas-server-3.5.2.1-release.z ...

  9. 重新开始学习c#啦,希望能坚持下去!

    过了这么多年,还是感觉自己喜欢C#,喜欢编程,虽然自己什么技术也没有:做的项目也不算是项目:

  10. HTML5课程大纲/学习路线

    HTML5课程大纲/学习路线 这是什么? 这个一个HTML技术路线的课程大纲/学习大纲. 你能用它做什么? 如果你是找工作的人, 利用本大纲, 你可以学习HTML5语言, 做一个HTML前端工程师, ...