BZOJ---1001:狼抓兔子

https://www.lydsy.com/JudgeOnline/problem.php?id=1001

Description

现在小朋友们最喜欢的"喜羊羊与灰太狼",话说灰太狼抓羊不到,但抓兔子还是比较在行的,

而且现在的兔子还比较笨,它们只有两个窝,现在你做为狼王,面对下面这样一个网格的地形:

 

左上角点为(1,1),右下角点为(N,M)(上图中N=4,M=5).有以下三种类型的道路 

1:(x,y)<==>(x+1,y) 

2:(x,y)<==>(x,y+1) 

3:(x,y)<==>(x+1,y+1) 

道路上的权值表示这条路上最多能够通过的兔子数,道路是无向的. 左上角和右下角为兔子的两个窝,

开始时所有的兔子都聚集在左上角(1,1)的窝里,现在它们要跑到右下解(N,M)的窝中去,狼王开始伏击

这些兔子.当然为了保险起见,如果一条道路上最多通过的兔子数为K,狼王需要安排同样数量的K只狼,

才能完全封锁这条道路,你需要帮助狼王安排一个伏击方案,使得在将兔子一网打尽的前提下,参与的

狼的数量要最小。因为狼还要去找喜羊羊麻烦.

Input

第一行为N,M.表示网格的大小,N,M均小于等于1000.

接下来分三部分

第一部分共N行,每行M-1个数,表示横向道路的权值. 

第二部分共N-1行,每行M个数,表示纵向道路的权值. 

第三部分共N-1行,每行M-1个数,表示斜向道路的权值. 

输入文件保证不超过10M

Output

输出一个整数,表示参与伏击的狼的最小数量.

Sample Input

3 4
5 6 4
4 3 1
7 5 3
5 6 7 8
8 7 6 5
5 5 5
6 6 6

Sample Output

14

 

思路:感谢LHJ大佬推荐我看的网络流的题,这种平面图的题可以转化成对偶图,用最短路求,对偶图这个东西还真是好好学了一下,有点意思,不过就是局限于平面图了,

然后这个题用网络流也能解,但是边是双向的,所以建边的时候反向边的流量也要是f,不能是0,第一次做这种无向图的网络流,不过不同的地方也就是建边,然后感觉我的模板真是够好了~~

代码:

先给一个转对偶图求最短的把,直接搜的一个代码,因为,对偶图就是一个转图过程,转完了,直接最短路就是最大流,也就是最小割了,所以并不算难,学了一个新知识点,还是不错的!

#include 
#include 
#include 
#include 
using namespace std;
const int maxn = 2000005;
const int maxm = 6000005;
char ch;
bool vis[maxn];
int n, m, x, ret, dis[maxn];
int tot, ter[maxm], nxt[maxm], len[maxm], lnk[maxn];
int read() {ch = getchar();ret = 0;while (!isdigit(ch)) {ch = getchar();}while (isdigit(ch)) {ret = (ret << 1) + (ret << 3) + (ch ^ '0');ch = getchar();}return ret;
}
int id(int i, int j, int k) {if (i > n || j < 1) {return 0;}if (i < 1 || j > m) {return n * m << 1 | 1;}return (i - 1) * m + j + k * n * m;
}
void adde(int u, int v, int w) {ter[tot] = v;len[tot] = w;nxt[tot] = lnk[u];lnk[u] = tot++;
}
int spfa(int s, int t) {queue que;que.push(s);memset(dis, 0x3f, sizeof(dis));dis[s] = s, vis[s] = 1;for (int u, v, w; !que.empty(); ) {u = que.front();que.pop();vis[u] = 0;for (int i = lnk[u]; ~i; i = nxt[i]) {v = ter[i], w = len[i];if (dis[v] > dis[u] + w) {dis[v] = dis[u] + w;if (!vis[v]) {vis[v] = 1;que.push(v);}}}}return dis[t];
}
int main() {memset(lnk, -1, sizeof(lnk));n = read(), m = read(), n--, m--;for (int i = 1; i <= n + 1; i++) {for (int j = 1; j <= m; j++) {x = read();adde(id(i, j, 1), id(i - 1, j, 0), x);adde(id(i - 1, j, 0), id(i, j, 1), x);}}for (int i = 1; i <= n; i++) {for (int j = 1; j <= m + 1; j++) {x = read();adde(id(i, j, 0), id(i, j - 1, 1), x);adde(id(i, j - 1, 1), id(i, j, 0), x);}}for (int i = 1; i <= n; i++) {for (int j = 1; j <= m; j++) {x = read();adde(id(i, j, 0), id(i, j, 1), x);adde(id(i, j, 1), id(i, j, 0), x);}}printf("%d\n", spfa(0, n * m << 1 | 1));return 0;
}

然后就是直接网络流的,直接套模板就可以,倒是不难。

#include 
using namespace std;
const int MAXN = 1000000 + 10;//点数
const int MAXM = 10000000+ 10;//边数,记得*2还是*4
const long long INF = 0x3f3f3f3f3f3f3f3fLL;
typedef long long ll;
namespace Dinic {struct Graph {struct Edge {int next,to,flow;};Edge edges[MAXM];int tot,heads[MAXN];Graph() : tot(0) {memset(heads,-1,sizeof(heads));}void addEdge(int u,int v,int f) {edges[tot].next = heads[u];edges[tot].to = v;edges[tot].flow = f;heads[u] = tot++;edges[tot].next = heads[v];edges[tot].to = u;edges[tot].flow = f;heads[v] = tot++;}} graph;int cur[MAXN],step[MAXN];int S,T;bool bfs() {queue que;que.push(S);memset(step,0,sizeof(step));step[S] = 1;while(!que.empty()) {int now = que.front();que.pop();for(int i = graph.heads[now];i != -1;i = graph.edges[i].next) {Graph::Edge &tmpEdge = graph.edges[i];if(tmpEdge.flow <= 0 || step[tmpEdge.to] != 0) continue;step[tmpEdge.to] = step[now] + 1;if(tmpEdge.to == T) return true;que.push(tmpEdge.to);}}return false;}ll dfs(int now,ll limit) {if(now == T) return limit;if(limit == 0) return 0;ll res = 0;for(int &i = cur[now];i != -1;i = graph.edges[i].next) {Graph::Edge &tmpEdge = graph.edges[i];if(tmpEdge.flow <= 0 || step[tmpEdge.to] != step[now] + 1) continue;ll tmpRes = dfs(tmpEdge.to,min(limit - res,static_cast(tmpEdge.flow)));tmpEdge.flow -= tmpRes;graph.edges[i ^ 1].flow += tmpRes;res += tmpRes;if(res == limit) break;}if(res == 0) {step[now] = 0;}return res;}ll dinic(int S,int T) {Dinic::S = S;Dinic::T = T;ll result = 0;while(bfs()) {memcpy(cur,graph.heads,sizeof(cur));ll tmp = dfs(S,INF);result += tmp;}return result;}
}
using namespace Dinic;
int main() {int n,m,s,t,x;scanf("%d%d%",&n,&m);for(int i=1;i<=n;i++)for(int j=1;j

 


本文来自互联网用户投稿,文章观点仅代表作者本人,不代表本站立场,不承担相关法律责任。如若转载,请注明出处。 如若内容造成侵权/违法违规/事实不符,请点击【内容举报】进行投诉反馈!

相关文章

立即
投稿

微信公众账号

微信扫一扫加关注

返回
顶部