题目大意:给出一个表格,每个表格指向周围四个格子中的一个,问你可以改变一些格子上的指向,问让所有格子都在圈中最小需要改变多少。
思路:所有的格子都在圈中,由于每个格子只能有一个出边,所以就要保证所有格子都有一个入边。建立费用流的模型,所有点向汇点连流量1费用0的边,表示要接受一个入边。S向所有点连一条流量1费用0的边,表示一条出边。一个格子向周围四个格子连边,流量1,如果方向与当前方向相符,那么费用0,否则费用1。之后跑费用流就是答案了。
CODE:
#include <queue> #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define MAX 10010 #define INF 0x3f3f3f3f #define S 0 #define T (MAX - 1) using namespace std; const int dx[] = {0,0,0,-1,1}; const int dy[] = {0,-1,1,0,0}; int G[256]; struct MinCostMaxFlow{ int head[MAX],total; int next[MAX],aim[MAX],cost[MAX],flow[MAX]; int f[MAX],from[MAX],p[MAX]; bool v[MAX]; MinCostMaxFlow() { total = 1; } void Add(int x,int y,int f,int c) { next[++total] = head[x]; aim[total] = y; flow[total] = f; cost[total] = c; head[x] = total; } void Insert(int x,int y,int f,int c) { Add(x,y,f,c); Add(y,x,0,-c); } bool SPFA() { static queue<int> q; while(!q.empty()) q.pop(); memset(f,0x3f,sizeof(f)); memset(v,false,sizeof(v)); f[S] = 0; q.push(S); while(!q.empty()) { int x = q.front(); q.pop(); v[x] = false; for(int i = head[x]; i; i = next[i]) if(flow[i] && f[aim[i]] > f[x] + cost[i]) { f[aim[i]] = f[x] + cost[i]; if(!v[aim[i]]) v[aim[i]] = true,q.push(aim[i]); from[aim[i]] = x; p[aim[i]] = i; } } return f[T] != INF; } int EdmondsKarp() { int re = 0; while(SPFA()) { int max_flow = INF; for(int i = T; i != S; i = from[i]) max_flow = min(max_flow,flow[p[i]]); for(int i = T; i != S; i = from[i]) { flow[p[i]] -= max_flow; flow[p[i]^1] += max_flow; } re += max_flow * f[T]; } return re; } }solver; int m,n; int num[20][20],cnt; char s[20][20]; int main() { G['L'] = 1,G['R'] = 2,G['U'] = 3,G['D'] = 4; cin >> m >> n; for(int i = 1; i <= m; ++i) { scanf("%s",s[i] + 1); for(int j = 1; j <= n; ++j) { num[i][j] = ++cnt; solver.Insert(S,cnt << 1,1,0); solver.Insert(cnt << 1|1,T,1,0); } } for(int i = 1; i <= m; ++i) for(int j = 1; j <= n; ++j) for(int k = 1; k <= 4; ++k) { int fx = i + dx[k],fy = j + dy[k]; if(!fx) fx = m; if(!fy) fy = n; if(fx > m) fx = 1; if(fy > n) fy = 1; if(k == G[s[i][j]]) solver.Insert(num[i][j] << 1,num[fx][fy] << 1|1,1,0); else solver.Insert(num[i][j] << 1,num[fx][fy] << 1|1,1,1); } cout << solver.EdmondsKarp() << endl; return 0; }