HihoCoder 1424Asa's Chess Problem
来源:互联网 发布:java页面跳转代码 编辑:程序博客网 时间:2024/06/05 19:15
一开始搜上下界没有见到费用流,就以为考不到,没有学。今天接着碰到了。。。
其实跟有源汇上下界最大流差不多。也是带了一些有花费的边。
对于这个题,一开始也没分析好。对于每行和每列的点,跟s相连的是已经有的黑子的数目,这是必须流的,也就是下界,上界很明显就是相同的。
然后跟e相连的是题目要求的上下界流量。然后交换怎么体现呢?题目中很亲民的给出每一对点要么行相同,要么列相同,很明显行相同,只会对列有影响,反之,只会对行有影响,那么我们就加上这样的一条边,对于不同的行或列连边,花费为1,下界0,上界1。
#include <cstdio>#include <queue>#include <cstring>#include <algorithm>#include <cstring>using namespace std;const int MAXN = 3000+5;const int inf = 1e9;typedef long long LL;int n;int sr[52],sc[52];int f[MAXN];int cnt,head[MAXN];int max_flow,min_cost,sum_flow;struct node{ int u,v,w,f,next;} edge[100000];void init(){ cnt = 0; memset(head,-1,sizeof head); memset(f,0,sizeof f); memset(sr,0,sizeof sr); memset(sc,0,sizeof sc);}void add(int u,int v,int w,int f){ edge[cnt].u = u; edge[cnt].v = v; edge[cnt].w = w; edge[cnt].f = f; edge[cnt].next = head[u]; head[u] = cnt++; edge[cnt].u = v; edge[cnt].v = u; edge[cnt].w = -w; edge[cnt].f = 0; edge[cnt].next = head[v]; head[v] = cnt++;}void Add(int u,int v,int w,int fl,int fh){ f[u] -= fl; f[v] += fl; add(u,v,w,fh-fl);}bool vis[MAXN];int dis[MAXN],pre[MAXN];bool spfa(int s,int e){ for(int i = 0; i <= e; ++i) { dis[i] = inf; pre[i] = -1; } queue<int>q; q.push(s); dis[s] = 0; while(!q.empty()) { int u = q.front(); q.pop(); vis[u] = 0; for(int i = head[u]; i != -1; i = edge[i].next) { int v = edge[i].v; int w = edge[i].w; int f = edge[i].f; if(f > 0 && dis[v] > dis[u] + w) { dis[v] = dis[u] + w; pre[v] = i; if(!vis[v]) { vis[v] = 1; q.push(v); } } } } if(pre[e] == -1)return 0; return 1;}void get_mincost(int s,int e){ max_flow = 0,min_cost = 0; while(spfa(s,e)) { int p = pre[e]; int flow = inf; while(p != -1) { flow = min(flow,edge[p].f); p = pre[edge[p].u]; } max_flow += flow; min_cost += flow*dis[e]; p = pre[e]; while(p != -1) { edge[p].f -= flow; edge[p^1].f += flow; p = pre[edge[p].u]; } } if(max_flow == sum_flow)printf("%d\n",min_cost); else puts("-1");}int tu[52][52];int main(){ while(~scanf("%d",&n)) { init(); for(int i = 1; i <= n; ++i) for(int j = 1; j <= n; ++j) { scanf("%d",&tu[i][j]); if(tu[i][j])sr[i]++,sc[j]++; } int s = 0,e = 2*n+1; for(int i = 1; i <= n; ++i)Add(s,i,0,sr[i],sr[i]); for(int i = 1; i <= n; ++i)Add(s,i+n,0,sc[i],sc[i]); int l,r; for(int i = 1; i <= n; ++i) { scanf("%d%d",&l,&r); Add(i,e,0,l,r); } for(int i = 1; i <= n; ++i) { scanf("%d%d",&l,&r); Add(i+n,e,0,l,r); } int u,v,u1,v1; for(int i = 0,R = n*n/2; i < R; ++i) { scanf("%d%d%d%d",&u,&v,&u1,&v1); if(tu[u][v] && !tu[u1][v1]) { if(u == u1) { Add(v+n,v1+n,1,0,1); } else Add(u,u1,1,0,1); } else if(!tu[u][v] && tu[u1][v1]) { if(u == u1) { Add(v1+n,v+n,1,0,1); } else Add(u1,u,1,0,1); } } int ss = e+1,ee = e+2; sum_flow = 0; for(int i = 0; i <= e; ++i) { if(f[i] > 0) { add(ss,i,0,f[i]); sum_flow += f[i]; } else add(i,ee,0,-f[i]); } add(e,s,0,inf); get_mincost(ss,ee); } return 0;}
阅读全文
0 0
- HihoCoder 1424Asa's Chess Problem
- Hihocoder 1424 Asa's Chess Problem (有源汇上下界最小费用流)
- [UVALive 7670] Asa's Chess Problem
- [acm/icpc2016北京赛区][hihocoder1424] Asa's Chess Problem 有上下界的费用流
- ASA's KeygenMe#2
- 8 Queens Chess Problem
- poj1321 Chess Problem
- 8 Queens Chess Problem
- poj-1321Chess Problem
- hihocoder 2015ACM-ICPC 北京赛区 Problem A. Xiongnu's Land
- hihoCoder 1260 String Problem I
- hihoCoder 1261 String Problem II
- hihoCoder 1260 String Problem I
- Problem S
- Problem-S
- Problem S
- UVa 750 - 8 Queens Chess Problem
- SWJTUOJ-2366 A chess Problem (easy)
- 第五周项目2— 建立链栈算法库
- Git-SSH 配置和使用
- 二分图最大匹配翻车记
- HDU5768:Lucky7(中国剩余定理 & 容斥)
- 属性动画
- HihoCoder 1424Asa's Chess Problem
- 上机一 F AlvinZH的儿时梦想——木匠篇
- UVALive
- Android自定义进度条(用画笔手动画出来)
- EJB学习总结
- 多线程学习
- 小学期 BlueSky学长与友人帐
- tomcat7安装配置
- JSP的内置对象