zoukankan      html  css  js  c++  java
  • BZOJ 3171: [Tjoi2013]循环格( 费用流 )

    每个点都在某个环中, 出度都为1, 只要让入度也全为1就可以满足题意了. 然后就是裸的最小费用最大流了. 

    ----------------------------------------------------------------------------

    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<deque>
    #include<bitset>
     
    using namespace std;
     
    #define X(x, y) (((x) * C + y) << 1)
    #define Y(x, y) (((x) * C + y) << 1 | 1)
     
    const int maxn = 20;
    const int maxv = maxn * maxn * 2;
    const int INF = 0X3F3F3F3F;
    const int dx[4] = {-1, 0, 0, 1};
    const int dy[4] = {0, 1, -1, 0};
    const char dc[4] = {'U', 'R', 'L', 'D'};
     
    int d[maxv], a[maxv];
    int R, C, V, S, T;
    char s[maxn];
    bitset<maxv> inq;
    deque<int> q;
     
    struct edge {
    int to, cap, cost;
    edge *next, *rev;
    } E[100000], *pt = E, *head[maxv], *p[maxv];
     
    inline void Add(int u, int v, int c, int w) {
    pt->to = v;
    pt->cap = c;
    pt->cost = w;
    pt->next = head[u];
    head[u] = pt++;
    }
     
    inline void AddEdge(int u, int v, int w) {
    Add(u, v, 1, w);
    Add(v, u, 0, -w);
    head[u]->rev = head[v];
    head[v]->rev = head[u];
    }
     
    void Solve() {
    int ans = 0;
    for( ; ; ) {
    inq.reset();
    memset(d, INF, sizeof(int) * V);
    d[S] = 0;
    a[S] = INF;
    q.push_back(S);
    while(!q.empty()) {
    int x = q.front(); q.pop_front();
    inq[x] = 0;
    for(edge* e = head[x]; e; e = e->next) if(e->cap && d[e->to] > d[x] + e->cost) {
    p[e->to] = e;
    d[e->to] = d[x] + e->cost;
    a[e->to] = min(a[x], e->cap);
    if(inq[e->to] == 0) {
    inq[e->to] = 1;
    if(!q.empty() && d[q.front()] > d[e->to])
    q.push_front(e->to);
    else
    q.push_back(e->to);
    }
    }
    }
    if(d[T] == INF)
    break;
    ans += d[T] * a[T];
    for(int x = T; x != S; x = p[x]->rev->to) {
    p[x]->cap -= a[T];
    p[x]->rev->cap += a[T];
    }
    }
    printf("%d ", ans);
    }
     
    void Init() {
    scanf("%d%d", &R, &C);
    V = R * C * 2;
    S = V++;
    T = V++;
    for(int i = 0; i < R; i++) {
    scanf("%s", s);
    for(int j = 0; j < C; j++) {
    AddEdge(S, X(i, j), 0);
    AddEdge(Y(i, j), T, 0);
    for(int d = 0; d < 4; d++) {
    int x = i + dx[d] + R, y = j + dy[d] + C;
    while(x >= R) x -= R;
    while(y >= C) y -= C;
    AddEdge(X(i, j), Y(x, y), s[j] != dc[d]);
    }
    }
    }
    }
     
    int main() {
    Init();
    Solve();
    return 0;
    }

    ----------------------------------------------------------------------------

    3171: [Tjoi2013]循环格

    Time Limit: 1 Sec  Memory Limit: 128 MB
    Submit: 672  Solved: 411
    [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<=R,L<=15

    Source

  • 相关阅读:
    推荐下自己的开源框架:DataMapFramework
    真的能无师自通吗?JAVA学习指导系列
    再回首,工作的第一个十年
    2个DataSet中的数据传递问题,请高手们多多指教。
    数据结构小结
    CDQZ_Training 2012524 词编码
    PowerDesigner显示Comment注释
    DDD基本元素
    使用FluorineFx.NET更新FMS中的SharedObject
    如何取消页面缓存
  • 原文地址:https://www.cnblogs.com/JSZX11556/p/5103747.html
Copyright © 2011-2022 走看看