bzoj 1458 士兵占领(最大流)
2016-03-23 14:34
441 查看
【题意】
n行m列,第i行必须放L[i],第j列必须放C[j],有障碍格,求满足条件至少需要放多少。
【思路】
至少放多少等价于最多不放多少。
对行列分别建XY点,则连边(S,Xi,a)(Yi,T,b),a表示i行可以放到数目-需要放的数目,b类似。对于不是障碍的格子(i,j),连边(Xi,Yj,1)。求最大流。
【代码】
n行m列,第i行必须放L[i],第j列必须放C[j],有障碍格,求满足条件至少需要放多少。
【思路】
至少放多少等价于最多不放多少。
对行列分别建XY点,则连边(S,Xi,a)(Yi,T,b),a表示i行可以放到数目-需要放的数目,b类似。对于不是障碍的格子(i,j),连边(Xi,Yj,1)。求最大流。
【代码】
#include<set> #include<cmath> #include<queue> #include<vector> #include<cstdio> #include<cstring> #include<iostream> #include<algorithm> #define trav(u,i) for(int i=front[u];i;i=e[i].nxt) #define FOR(a,b,c) for(int a=(b);a<=(c);a++) using namespace std; typedef long long ll; const int N = 4e2+10; const int inf = 1e9; ll read() { char c=getchar(); ll f=1,x=0; while(!isdigit(c)) { if(c=='-') f=-1; c=getchar(); } while(isdigit(c)) x=x*10+c-'0',c=getchar(); return x*f; } struct Edge { int u,v,cap,flow; }; struct Dinic { int n,m,s,t; int d ,cur ,vis ; vector<int> g ; vector<Edge> es; queue<int> q; void init(int n) { this->n=n; es.clear(); FOR(i,0,n) g[i].clear(); } void clear() { FOR(i,0,(int)es.size()-1) es[i].flow=0; } void AddEdge(int u,int v,int w) { es.push_back((Edge){u,v,w,0}); es.push_back((Edge){v,u,0,0}); m=es.size(); g[u].push_back(m-2); g[v].push_back(m-1); } int bfs() { memset(vis,0,sizeof(vis)); q.push(s); d[s]=0; vis[s]=1; while(!q.empty()) { int u=q.front(); q.pop(); FOR(i,0,(int)g[u].size()-1) { Edge& e=es[g[u][i]]; int v=e.v; if(!vis[v]&&e.cap>e.flow) { vis[v]=1; d[v]=d[u]+1; q.push(v); } } } return vis[t]; } int dfs(int u,int a) { if(u==t||!a) return a; int flow=0,f; for(int& i=cur[u];i<g[u].size();i++) { Edge& e=es[g[u][i]]; int v=e.v; if(d[v]==d[u]+1&&(f=dfs(v,min(a,e.cap-e.flow)))>0) { e.flow+=f; es[g[u][i]^1].flow-=f; flow+=f; a-=f; if(!a) 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; } } dc; int n,m,K,L ,C ,num1 ,num2 ,sum,mp ; int main() { n=read(),m=read(),K=read(); FOR(i,1,n) L[i]=read(),num1[i]=m; FOR(i,1,m) C[i]=read(),num2[i]=n; FOR(i,1,K) { int x=read(),y=read(); num1[x]--,num2[y]--; mp[x][y]=1; } dc.init(n+m+2); int S=0,T=n+m+1; FOR(i,1,n) FOR(j,1,m) if(!mp[i][j]) dc.AddEdge(i,n+j,1); int flag=0; FOR(i,1,n) if(num1[i]>=L[i]) dc.AddEdge(S,i,num1[i]-L[i]),sum+=num1[i]; else flag=1; FOR(i,1,m) if(num2[i]>=C[i]) dc.AddEdge(i+n,T,num2[i]-C[i]); else flag=1; if(flag) puts("JIONG"); else printf("%d",sum-dc.MaxFlow(S,T)); return 0; }
相关文章推荐
- #8号板测试汇总
- Hive取非Group by字段数据的方法
- leetcode--Best Time to Buy and Sell Stock
- Fragment详解(四)Fragment生命周期
- Android 截屏并保存
- Android安全专项-Apk加固
- Shell编程(四)---echo、printf
- 基于TestNG 与Selenium 的自动化测试设计与实施(二)
- css line-height:150%和1.5的不同之处
- 总结下并行和并发的差异
- db2 - 查看当前用户的权限
- Socket学习(一)
- mac 定时任务
- 微服务
- Android:Mac下WebView的debug
- Application Express中的resultful服务的插入语句
- 基于TestNG 与Selenium 的自动化测试设计与实施
- mysql修改max_allowed_packet
- HDU 2546 饭卡
- 500 G JAVA视频网盘分享