zoukankan      html  css  js  c++  java
  • bzoj3171: [Tjoi2013]循环格

    3171: [Tjoi2013]循环格

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 871  Solved: 551
    [Submit][Status][Discuss]

    Description

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

    ,你可以沿着箭头防线在格子间行走。即如果(r,c)是一个左箭头,那么走到(r,c-1);如果是右箭头那么走到(r,c+1);如果是上箭头那么走到(r-1,c);如果是下箭头那么走到(r+1,c);每一行和每一列都是循环的,即如果走出边界,你会出现在另一侧。
    一个完美的循环格是这样定义的:对于任意一个起始位置,你都可以i沿着箭头最终回到起始位置。如果一个循环格不满足完美,你可以随意修改任意一个元素的箭头直到完美。给定一个循环格,你需要计算最少需要修改多少个元素使其完美。

    Input

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

    Output

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

    Sample Input

    3 4
    RRRD
    URLL
    LRRR

    Sample Output

    2

    HINT

    首先有一个结论 每个点只存在于一个环中所以入度和出度都为1..(没想到结论退役系列)

    所以考虑用流

    拆一波点

    S向入点连边容量为1 出点向T连边容量为1

    向四联通的点连边容量为1费用为1...(如果是原来就有的箭头则费用为0)

     1 #include<bits/stdc++.h>
     2 #define rep(i,l,r) for(int i=l;i<=r;++i)
     3 using namespace std;
     4 const int N=102333,inf=2147483647;
     5 struct Edge{
     6     int to,next,from,c,w;
     7 }e[1000000];
     8 const int xx[4]={0,0,-1,1};
     9 const int yy[4]={-1,1,0,0};
    10 int head[N],tot=1,ans,dis[N],from[N],T,mp[100][100],nx,ny,cnt,n,m,num[100][100][2];
    11 bool used[N];
    12 char s[100][100];
    13 inline void ins(int u,int v,int w,int cost) {
    14      e[++tot].to=v; e[tot].next=head[u]; head[u]=tot; e[tot].w=w; e[tot].c=cost; e[tot].from=u;
    15 }
    16 
    17 inline bool spfa() {
    18      queue<int> q; for(int i=0;i<=T;i++) dis[i]=inf; dis[0]=0; q.push(0); used[0]=1;  
    19      while(!q.empty()) {
    20           int x=q.front(); q.pop();
    21           for(int k=head[x];k;k=e[k].next) 
    22            if(e[k].w>0&&dis[x]+e[k].c<dis[e[k].to]){
    23                   dis[e[k].to]=dis[x]+e[k].c; from[e[k].to]=k;
    24                   if(!used[e[k].to]) {
    25                         used[e[k].to]=1; q.push(e[k].to);
    26                   }
    27             }
    28            used[x]=0;
    29      }
    30      if(dis[T]==inf) return 0;else return 1;
    31 }
    32 
    33 inline void run() {
    34      int x=inf;
    35      for(int k=from[T];k;k=from[e[k].from]) x=min(x,e[k].w);
    36      for(int k=from[T];k;k=from[e[k].from]) {
    37           e[k].w-=x; e[k^1].w+=x; ans+=e[k].c*x;
    38      }
    39 }
    40 inline void insert(int u,int v,int w,int c){
    41     ins(u,v,w,c); ins(v,u,0,-c);
    42 }
    43 int main(){
    44     scanf("%d%d",&n,&m);
    45     rep(i,1,n) scanf("%s",s[i]+1);
    46     rep(i,1,n) rep(j,1,m) if(s[i][j]=='L') mp[i][j]=0;else if(s[i][j]=='R') mp[i][j]=1;
    47                           else if(s[i][j]=='U') mp[i][j]=2;else mp[i][j]=3;
    48     rep(i,1,n) rep(j,1,m) num[i][j][0]=++cnt,num[i][j][1]=++cnt;
    49     T=cnt+1;
    50     rep(i,1,n) rep(j,1,m) insert(0,num[i][j][0],1,0),insert(num[i][j][1],T,1,0);
    51     rep(i,1,n) rep(j,1,m) {
    52         rep(l,0,3) {
    53             nx=i+xx[l]; ny=j+yy[l];
    54 //            if(nx<1||nx>n||ny<1||ny>m) continue;
    55             if(nx<1) nx=n; if(nx>n) nx=1;
    56             if(ny<1) ny=m; if(ny>m) ny=1;
    57             if(mp[i][j]==l) insert(num[i][j][0],num[nx][ny][1],1,0);
    58             else insert(num[i][j][0],num[nx][ny][1],1,1);
    59         }
    60     }
    61     while(spfa()) run();
    62     printf("%d
    ",ans);
    63 }
    View Code
  • 相关阅读:
    HDU 4757 Tree 可持久化字典树 trie
    BZOJ 4198: [Noi2015]荷马史诗 哈夫曼树 k叉哈夫曼树
    BZOJ 3253 Fence Repair 哈夫曼树 水题
    BZOJ 3572: [Hnoi2014]世界树 虚树 树形dp
    2-SAT的一些题目
    二分图相关定理 最小点覆盖 最小路径覆盖 最大独立集 最小覆盖集
    POJ 1469 COURSES 二分图最大匹配 二分图
    快速排序
    排序算法:希尔排序
    霍夫曼编码实现
  • 原文地址:https://www.cnblogs.com/Bloodline/p/5885077.html
Copyright © 2011-2022 走看看