题意:给定一个网络 网络上有一些柱子 一些柱子上有一些? ?有跳跃能力d 可以从一个柱子跳到另一个柱子(只要小于等于d) 每个柱子有其容量跳一次-1 问有多少?能够跳出去?
一开始根本想不到用网络流来做
建图:
1 如果有? 将超级源点和?连1
2 如果有柱子 进行拆点 假设有两个柱子 两个柱子相连 容量为柱子的容量 网络流拆点:https://blog.youkuaiyun.com/xianpingping/article/details/79213802
3 对每个柱子进行dfs扫描 扫描范围为d (这里扫描很巧妙 注意看i 和j 的定义
如果能扫到 连路
如果能扫到地图外面 则与超级汇点相连
细节:
1 main 一开始开N 直接爆栈动都动不了
2 为了inmap 把n,m开全局 然后居然模板里面一直在改变m !
#include<cstring> #include<cstdio> #include<vector> #include<queue> #include<iostream> #include<algorithm> using namespace std; typedef long long ll; const int INF = 0x3f3f3f3f; const int N = 2000 ; # define inf 0x3f3f3f3f int p[N],s[N],e[N],v,c,k; struct Edge { int from, to, cap, flow; }; bool operator < (const Edge& a, const Edge& b) { return a.from < b.from || (a.from == b.from && a.to < b.to); } struct Dinic { int s,t; vector<Edge> edges; // 边数的两倍 vector<int> G[N]; // 邻接表,G[i][j]表示结点i的第j条边在e数组中的序号 bool vis[N]; // BFS使用 int d[N]; // 从起点到i的距离 int cur[N]; // 当前弧指针 void init(int n) { for(int i = 0; i <=n; i++) G[i].clear(); edges.clear(); } void AddEdge(int from, int to, int cap) { edges.push_back((Edge){from, to, cap, 0}); edges.push_back((Edge){to, from, 0, 0}); k = edges.size(); G[from].push_back(k-2); G[to].push_back(k-1); } bool BFS() { memset(vis, 0, sizeof(vis)); queue<int> q; q.push(s); vis[s] = 1; d[s] = 0; 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; } }g; vector<int> time; struct node { int si,num,ei,ti; }a[N]; int inmap(int x,int y,int n,int m) { if(x>=1&&x<=n&&y>=1&&y<=m) return 1; return 0; } int main() { char mp[30][30]; char xy[30][30]; int id[30][30]; int cas; scanf("%d",&cas); int d; int n,m; for(int kase=1;kase<=cas;kase++) { g.init(N); scanf("%d%d",&n,&d); for(int i=1;i<=n;i++) scanf("%s",mp[i]+1); for(int i=1;i<=n;i++) scanf("%s",xy[i]+1); int cnt=0; m=strlen(mp[1]+1); int num=0; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { if(xy[i][j]=='L')num++; if(mp[i][j]-'0')id[i][j]=++cnt; } int sorce=0; int end1=2*cnt+1; for(int i=1;i<=n;i++) for(int j=1;j<=m;j++) { int idx=mp[i][j]-'0'; if(idx) { if(xy[i][j]=='L')g.AddEdge(0,id[i][j],1); g.AddEdge(id[i][j],id[i][j]+cnt,idx); int flag=0; for(int dx=-d;dx<=d;dx++) for(int dy=abs(dx)-d;dy<=d-abs(dx);dy++ ) { if(inmap(i+dx,j+dy,n,m)) if(mp[i+dx][j+dy]-'0') g.AddEdge( id[i][j]+cnt,id[i+dx][j+dy],idx ); if(!inmap(i+dx,j+dy,n,m))flag=1; } if(flag)g.AddEdge(id[i][j]+cnt ,end1 ,idx); } } int left=num-g.Maxflow(sorce,end1); if(left==0) printf("Case #%d: no lizard was left behind.\n", kase); else if(left==1) printf("Case #%d: 1 lizard was left behind.\n", kase); else printf("Case #%d: %d lizards were left behind.\n", kase, left); } return 0; }