HDU 1565 1569 方格取数 (最小割)
2016-04-21 16:20
423 查看
链接:http://acm.hdu.edu.cn/showproblem.php?pid=1565
这两题其实是同一题,一个数据小,一个数据大,据说数据小的时候能用状压DP。哇!好神奇呀,可是我不会。就用dinic搞了一下。
思路:假设选了(x,y)点,那么(x,y)周围的点都不能选了。那么将图分为两部分,一部分是(x+y)%2==0,另一部分是(x+y)%2==1。所以在一个点和他周围的点中,会做一个选择,要么选这个点,要么选他周围的某些点。建图就可以按照这个思路建了,源点跟(x+y)是偶数的点连边,流量是该点的权值。(x+y)是奇数的点跟汇点连边,流量是权值。然后每个(x+y)是偶数的点,跟他周围的点连边,权值是INF。这样就是一个最小割模型,可以用最大流求解。但是这个解出来的答案是最小割,是权值最小的选择方案,怎么办呢?
选择不是最小割中的点。如果选择最小权值时没有非法选择的话,那么选择其余所有点也不会非法,于是将所有权值加起来减去最小割的权值就是答案了。
这两题其实是同一题,一个数据小,一个数据大,据说数据小的时候能用状压DP。哇!好神奇呀,可是我不会。就用dinic搞了一下。
思路:假设选了(x,y)点,那么(x,y)周围的点都不能选了。那么将图分为两部分,一部分是(x+y)%2==0,另一部分是(x+y)%2==1。所以在一个点和他周围的点中,会做一个选择,要么选这个点,要么选他周围的某些点。建图就可以按照这个思路建了,源点跟(x+y)是偶数的点连边,流量是该点的权值。(x+y)是奇数的点跟汇点连边,流量是权值。然后每个(x+y)是偶数的点,跟他周围的点连边,权值是INF。这样就是一个最小割模型,可以用最大流求解。但是这个解出来的答案是最小割,是权值最小的选择方案,怎么办呢?
选择不是最小割中的点。如果选择最小权值时没有非法选择的话,那么选择其余所有点也不会非法,于是将所有权值加起来减去最小割的权值就是答案了。
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<cctype> #include<string> #include<iostream> #include<vector> #include<map> #include<queue> using namespace std; #define PB push_back typedef long long ll; typedef pair<int,int> pii; const int INF=1e9+7; #define lson l,m,rt<<1 #define rson m+1,r,rt<<1|1 struct EE{ int to,cap,next; EE(){} EE(int to,int cap,int next):to(to),cap(cap),next(next){} }edge[100000]; int n; int st,ed,Ecnt,head[410],d[410]; int go[4][2]={{1,0},{-1,0},{0,1},{0,-1}}; inline int id(int x,int y){ return x*n+y+1; } inline bool judge(int x,int y){ return x>=0&&x<n&&y>=0&&y<n; } inline void add(int s,int t,int v){ edge[Ecnt]=EE(t,v,head[s]); head[s]=Ecnt++; edge[Ecnt]=EE(s,0,head[t]); head[t]=Ecnt++; } bool BFS(){ memset(d,-1,sizeof d); d[st]=0; queue<int> Q;Q.push(st); while(!Q.empty()){ int s=Q.front();Q.pop(); for(int i=head[s];~i;i=edge[i].next){ EE e=edge[i]; if(e.cap>0&&d[e.to]<0){ d[e.to]=d[s]+1;Q.push(e.to); } } } return d[ed]!=-1; } int DFS(int s,int t,int flow){ if(s==ed||!flow)return flow; int ans=0; for(int i=head[s];~i;i=edge[i].next){ EE &e=edge[i]; if(e.cap>0&&d[e.to]==d[s]+1){ int ff=DFS(e.to,t,min(flow,e.cap)); if(ff>0){ e.cap-=ff; edge[i^1].cap+=ff; flow-=ff; ans+=ff; if(!flow)break; } } } if(!ans)d[s]=-1; return ans; } int dinic(){ int ans=0; while(BFS()){ ans+=DFS(st,ed,INF); } return ans; } int main(){ while(scanf("%d",&n)!=EOF){ st=0;ed=n*n+1; int sum=0; Ecnt=0;memset(head,-1,sizeof head); for(int i=0;i<n;i++){ for(int j=0;j<n;j++){ int x;scanf("%d",&x); sum+=x; if((i+j)&1){ add(id(i,j),ed,x); } else{ add(st,id(i,j),x); for(int k=0;k<4;k++){ int x=i+go[k][0],y=j+go[k][1]; if(judge(x,y)){ add(id(i,j),id(x,y),INF); } } } } } printf("%d\n",sum-dinic()); } return 0; }
相关文章推荐
- 《编写高质量代码 : 改善C#程序的157个建议》读书笔记 1-10
- React-native第一课,Button的添加
- 一点点
- JS学习4(引用类型)
- HTML + CSS 之替换元素与非替换元素
- 两位数乘一位数
- iOS ---使用定位需要的依赖库
- 最终实现任意个数字排序
- json数据中的某一个字段进行快速排序quicksort
- python(14)类,方法,对象,实例
- leetcode 4. Median of Two Sorted Arrays
- Spring容器启动后注入service到Servlet并自动执行
- Android创建简单发送和接收短信应用
- 搜集的iOS相关网站与微博
- 单数乘单数
- SAP HANA SQL执行计划(SAP HANA SQL explain plan)
- UML -六种关系
- 配置文件——WebApp.config文件读取和修改
- 对任意十个数求和(5)
- 阶乘