您的位置:首页 > 理论基础 > 计算机网络

poj 1486 网络流+tarjan

2016-09-04 15:07 253 查看
题意:给一堆矩形和一些点,每个矩形必须对应一个点,求对应的点唯一的矩形个数。

如果点在矩形内部那么从点向矩形连流量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;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  poj