【bzoj1458】【士兵占领】【网络流】
2016-04-19 08:52
676 查看
Description
有一个M * N的棋盘,有的格子是障碍。现在你要选择一些格子来放置一些士兵,一个格子里最多可以放置一个士兵,障碍格里不能放置士兵。我们称这些士兵占领了整个棋盘当满足第i行至少放置了Li个士兵, 第j列至少放置了Cj个士兵。现在你的任务是要求使用最少个数的士兵来占领整个棋盘。Input
第一行两个数M, N, K分别表示棋盘的行数,列数以及障碍的个数。 第二行有M个数表示Li。 第三行有N个数表示Ci。 接下来有K行,每行两个数X, Y表示(X, Y)这个格子是障碍。Output
输出一个数表示最少需要使用的士兵个数。如果无论放置多少个士兵都没有办法占领整个棋盘,输出”JIONG!” (不含引号)Sample Input
4 4 41 1 1 1
0 1 0 3
1 4
2 2
3 3
4 3
Sample Output
4数据范围
M, N <= 100, 0 <= K <= M * N
题解:
源点向每一行连容量为该行所需士兵数量的边.
每一列向汇点连容量为该列所需士兵数量的边.
对于每个可以摆放的点(x,y).
x向y连容量为1的边.
sigma(L[i])+sigma(C[i])-最小割即可.
代码:
#include<iostream> #include<cstdio> #include<cstring> #define N 300 #define M 20000 #define inf 2100000000 using namespace std; int n,m,x,y,k,sum1,sum2,T,next[M<<1],point ,h ,l ; int dis ,pre ,gap ,cur ,cnt=1,map ,num1 ,num2 ; bool f; struct use{int st,en,v;}e[M<<1]; void add(int x,int y,int v){ next[++cnt]=point[x];point[x]=cnt; e[cnt].st=x;e[cnt].en=y;e[cnt].v=v; next[++cnt]=point[y];point[y]=cnt; e[cnt].st=y;e[cnt].en=x;e[cnt].v=0; } int isap(){ int i,mn,ans(0),u(1); gap[0]=T; for (i=1;i<=T;i++) cur[i]=point[i]; while (dis[1]<T){ f=false; for (i=cur[u];i;i=next[i]) if (e[i].v&&dis[e[i].en]+1==dis[u]){cur[u]=i;f=true;break;} if (f){ pre[u=e[i].en]=i; if (u==T){ mn=inf; for (i=T;i!=1;i=e[pre[i]].st) mn=min(mn,e[pre[i]].v); ans+=mn; for (i=T;i!=1;i=e[pre[i]].st) e[pre[i]].v-=mn,e[pre[i]^1].v+=mn; u=1; } } else{ gap[dis[u]]--;if (!gap[dis[u]]) return ans; for (mn=T,i=point[u];i;i=next[i]) if (e[i].v) mn=min(mn,dis[e[i].en]); gap[dis[u]=mn+1]++;cur[u]=point[u]; if (u!=1) u=e[pre[u]].st; } } return ans; } int main(){ scanf("%d%d%d",&n,&m,&k);T=n+m+2; for (int i=1;i<=n;i++){ scanf("%d",&h[i]); add(1,i+1,h[i]); sum1+=h[i]; } for (int i=1;i<=m;i++){ scanf("%d",&l[i]); add(i+n+1,T,l[i]); sum2+=l[i]; } for (int i=1;i<=k;i++){ scanf("%d%d",&x,&y); map[x][y]=1; } for (int i=1;i<=n;i++) for (int j=1;j<=m;j++) if (!map[i][j]) add(i+1,j+n+1,1),num1[i]++,num2[j]++; for (int i=1;i<=n;i++)if (num1[i]<h[i]){cout<<"JIONG!";return 0;} for (int i=1;i<=m;i++)if (num2[i]<l[i]){cout<<"JIONG!";return 0;} int t=sum1+sum2-isap(); cout<<t<<endl; }
相关文章推荐
- 【收藏用】切勿转载--Android网络编程(一)HTTP协议原理
- 实例讲解虚拟机3种网络模式(桥接、nat、Host-only)
- 自定义扇形进度条、异步加载网络图片、Activity疯狂旋转动画
- web day11 JSP基础,Cookie,HttpSession,验证码
- bzoj1834 [ZJOI2010]network 网络扩容
- HDU 4725-J - The Shortest Path in Nya Graph-增点建图-层次网络-最短路
- HTTP 请求方式: GET和POST的比较 3
- 浅谈HTTP中Get与Post的区别
- [网络编程]——TCP_Socket通信_聊天室_客户端多线程.初步形成
- Android中的异步网络请求
- 文化部、广电总局联合出击:网络直播、未成年人娱乐节目、papi酱遭遇封杀?
- 简单的springmvc部署后出现HTTP Status 500 - Servlet.init()
- 利用HttpClient.class.php本地模拟post请求
- httpSession 和 hibernate Session的区别
- TCP三次握手和四次挥手
- 厦门巨游网络科技有限公司(HOTPOWER)承接游戏UI外包
- windows下使用apache配置https服务器
- TCP/IP协议
- TCP/UDP 学习
- Windows下常用网络测试命令