zoukankan      html  css  js  c++  java
  • [TJOI2013]循环格

    费用流,

    因为要求全部都是回路, 每个点出入度都为1,拆点分别代表出点和入点,剩下不多说。

    注意边界可以走 即n->1

    /**
     * Problem:Grid
     * Author:Shun Yao
     * Time:2013.5.21
     * Result:Accepted
     * Memo:CostFlow
     */
    
    #include <cstring>
    #include <cstdlib>
    #include <cstdio>
    
    using namespace std;
    
    const long dir[2][4] = {{0, 0, -1, 1}, {-1, 1, 0, 0}}, Maxt = 452;
    
    long s, t, ans, p2[Maxt], q[Maxt], *l, *r;
    long d[Maxt];
    char inq[Maxt];
    
    class gnode {
    public:
    	long v, w;
    	char f;
    	gnode *op, *next;
    	gnode() {}
    	~gnode() {}
    	gnode(long V, long W, char F, gnode *o, gnode *ne):v(V), w(W), f(F), op(o), next(ne) {}
    } *g[Maxt], *p1[Maxt];
    
    void add(long x, long y, long w) {
    	g[x] = new gnode(y, w, 1, 0, g[x]);
    	g[y] = new gnode(x, -w, 0, g[x], g[y]);
    	g[x]->op = g[y];
    }
    
    char spfa() {
    	static long i;
    	static gnode *e;
    	memset(d, 0x7f, sizeof d);
    	d[s] = 0;
    	memset(inq, 0, sizeof inq);
    	inq[s] = 1;
    	l = q;
    	*l = s;
    	r = l + 1;
    	while (l != r) {
    		inq[*l] = 0;
    		if (d[*l] == 0x7f7f7f7f) {
    			++l;
    			if (l == q + Maxt)
    				l = q;
    			continue;
    		}
    		for (e = g[*l]; e; e = e->next)
    			if (e->f && d[e->v] > d[*l] + e->w) {
    				d[e->v] = d[*l] + e->w;
    				p1[e->v] = e;
    				p2[e->v] = *l;
    				if (!inq[e->v]) {
    					inq[e->v] = 1;
    					*r = e->v;
    					++r;
    					if (r == q + Maxt)
    						r = q;
    				}
    			}
    		++l;
    		if (l == q + Maxt)
    			l = q;
    	}
    	if (d[t] == 0x7f7f7f7f)
    		return 0;
    	ans += d[t];
    	for (i = t; i != s; i = p2[i]) {
    		p1[i]->f = !p1[i]->f;
    		p1[i]->op->f = !p1[i]->op->f;
    	}
    	return 1;
    }
    
    int main() {
    	static long n, m, i, j, k, x, y, z;
    	static char ch;
    	freopen("grid.in", "r", stdin);
    	freopen("grid.out", "w", stdout);
    	scanf("%ld%ld", &n, &m);
    	s = (n * m) << 1;
    	t = s + 1;
    	for (i = 0; i < n; ++i) {
    		for (j = 0; j < m; ++j) {
    			add(s, i * m + j, 0);
    			add(i * m + j + n * m, t, 0);
    			scanf(" %c", &ch);
    			switch (ch) {
    			case 'L':z = 0;break;
    			case 'R':z = 1;break;
    			case 'U':z = 2;break;
    			case 'D':z = 3;break;
    			}
    			for (k = 0; k < 4; ++k) {
    				x = (i + dir[0][k] + n) % n;
    				y = (j + dir[1][k] + m) % m;
    				add(i * m + j, x * m + y + n * m, k != z);
    			}
    		}
    	}
    	ans = 0;
    	while (spfa());
    	printf("%ld", ans);
    	fclose(stdin);
    	fclose(stdout);
    	return 0;
    }
    
  • 相关阅读:
    sql行列互转
    用户角色权限设计思路
    树节点类型数据的Datatable转Json
    [C#]最简单的Base64加密解密
    WEB打印控件Lodop(V6.x)使用说明及样例
    js代码 设为首页 加入收藏
    Json字符转化成对象
    C++函数返回值为const
    7.双指针(two pointer)
    线程同步与锁
  • 原文地址:https://www.cnblogs.com/hsuppr/p/3091581.html
Copyright © 2011-2022 走看看