3171: [Tjoi2013]循环格
Time Limit: 1 Sec Memory Limit: 128 MBSubmit: 1149 Solved: 727
[ 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
RRRD
URLL
LRRR
Sample Output
2
HINT
1<=R,L<=15
Source
#include<cstdio> #include<algorithm> #include<cstring> #include<vector> #include<queue> using namespace std; typedef long long LL; typedef double DL; const int INF = 2147483647; const int maxn = 20; const int maxp = maxn * maxn * 2; const int maxm = maxp * maxp * 2; const int d[4][2] = {{-1,0},{1,0},{0,1},{0,-1}}; struct data{ int to,cap,flow,c; }e[maxm]; vector<int> G[maxp]; int n,m,s,t,tot,tote = -1,ans; int x[maxn][maxn],y[maxn][maxn]; int pri[300],dis[maxp],a[maxp],pre[maxp],exist[maxp],Q[maxp]; char gra[maxn][maxn]; inline int getint() { int ret = 0,f = 1; char c = getchar(); while (c < '0' || c > '9') { if (c == '-') f = -1; c = getchar(); } while (c >= '0' && c <= '9') ret = ret * 10 + c - '0',c = getchar(); return ret * f; } inline int spfa() { memset(a,0,sizeof(a)); memset(pre,0,sizeof(pre)); memset(exist,0,sizeof(exist)); for (int i = 1; i <= tot; i++) dis[i] = INF; int head = 0,tail = 0; dis[Q[++tail] = s] = 0; a[s] = INF; while (head < tail) { int u = Q[++head]; exist[u] = 0; for (int i = 0; i < G[u].size(); i++) { data E = e[G[u][i]]; if (E.cap == E.flow) continue; if (dis[E.to] > dis[u] + E.c) { a[E.to] = min(a[u],E.cap - E.flow); dis[E.to] = dis[u] + E.c; pre[E.to] = G[u][i] ^ 1; if (!exist[E.to]) exist[Q[++tail] = E.to] = 1; } } } if (!a[t]) return 0; int now = t; while (now != s) { e[pre[now] ^ 1].flow += a[t]; e[pre[now]].flow -= a[t]; now = e[pre[now]].to; } ans += a[t] * dis[t]; return 1; } inline void add(int u,int v,int cap,int c) { e[++tote] = (data){v,cap,0,c}; G[u].push_back(tote); e[++tote] = (data){u,cap,cap,-c}; G[v].push_back(tote); } inline char getcom() { char c = getchar(); while (c != 'U' && c != 'R' && c != 'D' && c != 'L') c = getchar(); return c; } int main() { pri['U'] = 0; pri['D'] = 1; pri['R'] = 2; pri['L'] = 3; n = getint(); m = getint(); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) x[i][j] = ++tot , y[i][j] = ++tot; for (int i = 1; i <= n; i++) y[i][0] = y[i][m] , y[i][m + 1] = y[i][1]; for (int j = 1; j <= m; j++) y[0][j] = y[n][j] , y[n + 1][j] = y[1][j]; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) gra[i][j] = getcom(); s = ++tot; t = ++tot; for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) for (int k = 0; k <= 3; k++) add(x[i][j],y[i + d[k][0]][j + d[k][1]],1,pri[gra[i][j]] != k); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) add(s,x[i][j],1,0); for (int i = 1; i <= n; i++) for (int j = 1; j <= m; j++) add(y[i][j],t,1,0); while (spfa()); printf("%d",ans); return 0; }