原题在此:http://acm.hdu.edu.cn/showproblem.php?pid=3046
小小思路:寒假一月月赛遇到的题,最小割、最大流的建图一般都是加一个源点S,汇点T
然后S与worf的边权值连INF,sheep与T的边权值为INF
这样总能确保最小割划分时worf在S一边,sheep在T一边
然后便是一个建图过程。 一个点的上下左右若是坐标合法,则各连权值为1的边。
ps:自己一开始始终理解不了题意,原来只要能把sheep围住即可,fence应该是建在两个坐标(空地与空地,狼与空地,羊与空地都可)之间。
最小割定义:起点在S中,终点在T中的所有边的容量和。 (蓝图论书上说的净流量有问题)
附个代码。
//小trick,maxn开的应该大于n*m //一开始自己老是以为是200左右。 #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #include <vector> #include <cmath> #include <queue> #include <stack> #include <map> #include <set> using namespace std; #define clr(x) memset(x,0,sizeof(x)) #define fp1 freopen("in.txt","r",stdin) #define fp2 freopen("out.txt","w",stdout) #define pb push_back #define INF 0x3c3c3c3c typedef long long LL; const int maxn = 50000 + 10; //结点最多数目, struct Edge{ //代表一条from->to容量为cap,流量为flow的弧 int from, to, cap, flow; }; struct Dinic{ int n, m, s, t; //结点数,边数(包括反向弧), 源点、汇点号 vector<Edge> edges; //边表 edge[e]与edge[e^1]互为反向弧 vector<int> G[maxn]; bool vis[maxn]; int d[maxn]; int cur[maxn]; void AddEdge(int from, int to, int cap){ edges.push_back((Edge){from, to, cap, 0}); edges.push_back((Edge){to, from, 0, 0}); int m = edges.size(); G[from].push_back(m-2); G[to].push_back(m-1); } bool BFS(){ memset(vis, 0, sizeof(vis)); queue<int> Q; Q.push(s); d[s] = 0; vis[s] = 1; while(!Q.empty()){ int x = Q.front(); Q.pop(); for(int i = 0;i < G[x].size();i++){ Edge& e = edges[G[x][i]]; if(!vis[e.to] && e.cap>e.flow){ vis[e.to] = 1; d[e.to] = d[x] + 1; Q.push(e.to); } } } return vis[t]; } int DFS(int x, int a){ if(x==t || a==0) return a; int flow = 0, f; for(int &i = cur[x];i < G[x].size();i++){ Edge& e = edges[G[x][i]]; if(d[x]+1==d[e.to] && (f=DFS(e.to, min(a, e.cap-e.flow)))>0){ e.flow += f; edges[G[x][i]^1].flow -= f; flow += f; a -= f; if(a == 0) break; } } return flow; } int Maxflow(int s, int t){ this->s = s; this->t = t; int flow = 0; while(BFS()){ memset(cur, 0, sizeof(cur)); flow += DFS(s, INF); } return flow; } }; int n, m; int a[205][205]; int pos[205][205]; int wcnt, scnt; int R(int i, int j){ if(i<=n&&i>=0&&j>=0&&j<=m) return 1; else return 0; } int main() { //fp1; int ncase = 1; while(scanf("%d %d", &n, &m) == 2){ // wcnt = 1, scnt = 1; int i,j,k,l; clr(a); for(i = 1;i <= n;i++){ for(j = 1;j <= m;j++){ scanf("%d", &a[i][j]); } } int s = 0, t = n*m+1; Dinic test; for(i = 1;i <= n;i++){ for(j = 1;j <= m;j++){ int te = (i-1)*m+j; if(i<n) test.AddEdge(te,te+m,1); if(i>1) test.AddEdge(te,te-m,1); if(j<m) test.AddEdge(te,te+1,1); if(j>1) test.AddEdge(te,te-1,1); if(a[i][j]==1) test.AddEdge(te,t,INF); if(a[i][j]==2) test.AddEdge(s,te,INF); } } printf("Case %d:\n",ncase++); printf("%d\n", test.Maxflow(s,t)); } return 0; }
worf eat sheep, 最小割, hdu3046,布布扣,bubuko.com
原文地址:http://blog.csdn.net/cgf1993/article/details/25867281