poj 1486 网络流+tarjan
2016-09-04 15:07
253 查看
题意:给一堆矩形和一些点,每个矩形必须对应一个点,求对应的点唯一的矩形个数。
如果点在矩形内部那么从点向矩形连流量1的边,从S向点连流量1的边,从矩形向T连流量1的边。跑网络流。
跑出来的东西是一种方案。将这种方案变成另一种方案只需要找到所有边剩余流量都为1的环,这样的环一定是偶环且正向边和反向边交替排列。那么把正向边流量流掉,把反向边流量退回就是一种新方案。
那么只需要跑一遍tarjan,如果矩形和在网络流中和他匹配的点不在一个强连通分量中,那么这个矩形的方案就是唯一的。
如果点在矩形内部那么从点向矩形连流量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 2100000 int n,Case; int X1 ,X2 ,Y1 ,Y2 ; 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; }
相关文章推荐
- 初学ACM - 组合数学基础题目PKU 1833
- POJ ACM 1001
- POJ ACM 1002
- 1611:The Suspects
- POJ1089 区间合并
- POJ 2159 Ancient Cipher
- POJ 2635 The Embarrassed Cryptographe
- POJ 3292 Semi-prime H-numbers
- POJ 2773 HAPPY 2006
- POJ 3090 Visible Lattice Points
- POJ-2409-Let it Bead&&NYOJ-280-LK的项链
- POJ-1695-Magazine Delivery-dp
- POJ1523 SPF dfs
- POJ-1001 求高精度幂-大数乘法系列
- POJ-1003 Hangover
- POJ-1004 Financial Management
- [数论]poj2635__The Embarrassed Cryptographer
- [二分图匹配]poj2446__Chessboard
- [强连通分量]poj2186_Popular Cows
- POJ1050 最大子矩阵和