poj 1486 网络流+tarjan
来源:互联网 发布:python split 多个空格 编辑:程序博客网 时间:2024/05/16 01:35
题意:给一堆矩形和一些点,每个矩形必须对应一个点,求对应的点唯一的矩形个数。
如果点在矩形内部那么从点向矩形连流量1的边,从S向点连流量1的边,从矩形向T连流量1的边。跑网络流。
跑出来的东西是一种方案。将这种方案变成另一种方案只需要找到所有边剩余流量都为1的环,这样的环一定是偶环且正向边和反向边交替排列。那么把正向边流量流掉,把反向边流量退回就是一种新方案。
那么只需要跑一遍tarjan,如果矩形和在网络流中和他匹配的点不在一个强连通分量中,那么这个矩形的方案就是唯一的。
#include <queue>#include <stdio.h>#include <string.h>#include <algorithm>using namespace std;#define N 1100#define inf 1e9#define M 2100000int n,Case;int X1[N],X2[N],Y1[N],Y2[N];struct awork_flow{ int head[N<<1],nex[M],to[M],val[M],tot; int deep[N<<1],S,T; queue<int>que; void init() { memset(head,0,sizeof(head)); tot=1; } void add(int x,int y,int z) { tot++; nex[tot]=head[x];head[x]=tot; to[tot]=y;val[tot]=z; } int dfs(int x,int mv) { if(x==T)return mv; int tmp=0; for(int i=head[x];i;i=nex[i]) if(val[i]&&deep[to[i]]==deep[x]+1) { int t=dfs(to[i],min(mv-tmp,val[i])); if(!t)deep[to[i]]=-1; tmp+=t;val[i]-=t; val[i^1]+=t; if(tmp==mv)break; } return tmp; } int bfs() { while(!que.empty())que.pop(); que.push(S); memset(deep,-1,sizeof(deep)); deep[S]=0; while(!que.empty()) { int tmp=que.front();que.pop(); for(int i=head[tmp];i;i=nex[i]) if(val[i]&&deep[to[i]]==-1) { deep[to[i]]=deep[tmp]+1; if(to[i]==T)return 1; que.push(to[i]); } } return 0; } int dinic() { int ret=0; while(bfs()) ret+=dfs(S,inf); return ret; }}a;struct Tarjan{ int dfn[N<<1],low[N<<1],bel[N<<1]; int st[N<<1],top,cnt,ins[N<<1],tot; void init() { top=0;cnt=0;tot=0; memset(dfn,0,sizeof(dfn)); memset(low,0,sizeof(low)); } void tarjan(int x) { dfn[x]=low[x]=++cnt;st[++top]=x; ins[x]=1; for(int i=a.head[x];i;i=a.nex[i]) if(a.val[i]) { if(!dfn[a.to[i]])tarjan(a.to[i]),low[x]=min(low[x],low[a.to[i]]); else if(ins[a.to[i]])low[x]=min(low[x],dfn[a.to[i]]); } if(dfn[x]==low[x]) { int t=st[top--];bel[t]=++tot; ins[t]=0; while(t!=x) { t=st[top--]; bel[t]=tot;ins[t]=0; } } }}b;int main(){ while(scanf("%d",&n)!=EOF&&n) { for(int i=1;i<=n;i++) scanf("%d%d%d%d",&X1[i],&X2[i],&Y1[i],&Y2[i]); a.init();b.init(); for(int i=1,x,y;i<=n;i++) { scanf("%d%d",&x,&y); for(int j=1;j<=n;j++) if(X1[j]<=x&&X2[j]>=x&&Y1[j]<=y&&Y2[j]>=y) a.add(i+n,j,1),a.add(j,i+n,0); } a.S=n*2+1;a.T=n*2+2; for(int i=1;i<=n;i++)a.add(a.S,i+n,1),a.add(i+n,a.S,0); for(int i=1;i<=n;i++)a.add(i,a.T,1),a.add(a.T,i,0); a.dinic(); for(int i=1;i<=a.T;i++) if(!b.dfn[i])b.tarjan(i); int cnt=0; printf("Heap %d\n",++Case); for(int i=1;i<=n;i++) for(int j=a.head[i];j;j=a.nex[j]) if(a.val[j]&&a.to[j]>n&&a.to[j]<a.S&&b.bel[i]!=b.bel[a.to[j]]) { cnt++; printf("(%c,%d) ",i+'A'-1,a.to[j]-n); } if(!cnt)puts("none"); else puts(""); puts(""); } return 0;}
0 0
- poj 1486 网络流+tarjan
- poj 2553 tarjan算法
- poj 2186 tarjan算法
- tarjan求割点 poj 1144
- poj 1470--tarjan--LCA
- POJ 3694 Tarjan+LCA
- poj 2553 tarjan
- poj--1470--tarjan算法
- poj 1523 tarjan求割点
- poj 2553 Tarjan
- poj 1904 Tarjan
- POJ 1470 Tarjan算法
- POJ 1236 Tarjan算法
- POJ 2186 Tarjan
- POJ 2553 Tarjan
- POJ 3114 Tarjan+Dijkstra
- POJ 1523 Tarjan求割点
- POJ 3180 Tarjan
- VS2015使用小技巧 控制台代码写完后生成的exe程序在哪里
- Prim算法和Kruskal算法(最小生成树)
- 近期小结
- http://www.cnblogs.com/nzbbody/p/3504199.html
- Java基础方法的初使用规则
- poj 1486 网络流+tarjan
- zigzag数组的C语言实现
- js中typeof的用法
- 主键约束与唯一性约束的区别
- java/android 设计模式学习笔记(19)---状态模式
- CSU 1811 Tree Intersection
- 用网络线程编写的石头剪刀布
- <boost-05> boost::filesystem 常用命令集合
- TQ210——按键(中断查询法)