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

HDU 3605 Escape 网络流最大流 合并点

2016-05-21 09:30 561 查看
表面上看这是一道很明显的网络流题目,只要把源点连到所有人上,每个人再连到星球上,星球再连接到汇点即可,但是由于点数太多导致边数也很多,最终超时。

实际上每个人最多就只有10个星球可以选择,也就是1024种可能,那么只要人数超过1024,必定会出现重复的选择情况,而且重复的次数相当多,如果我们把这些选择相同的人合并起来,并且把对应的边的容量也合并起来,就可以将点缩减至1036个,从而降低时间复杂度。
Problem - 3605
[align=center] [/align]

Escape

Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)
Total Submission(s): 8412    Accepted Submission(s): 1902

[align=left]Problem Description[/align]
2012 If this is the end of the world how to do? I do not know how. But now scientists have found that some stars, who can live, but some people do not fit to live some of the planet. Now scientists want your help, is to determine what all of people can live in these planets.

[align=left]Input[/align]
More set of test data, the beginning of each data is n (1 <= n <= 100000), m (1 <= m <= 10) n indicate there n people on the earth, m representatives m planet, planet and people labels are from 0. Here are n lines, each line represents a suitable living conditions of people, each row has m digits, the ith digits is 1, said that a person is fit to live in the ith-planet, or is 0 for this person is not suitable for living in the ith planet.
The last line has m digits, the ith digit ai indicates the ith planet can contain ai people most..
0 <= ai <= 100000

[align=left]Output[/align]
Determine whether all people can live up to these stars
If you can output YES, otherwise output NO.

[align=left]Sample Input[/align]

1 1 1 1 2 2 1 0 1 0 1 1

[align=left]Sample Output[/align]

YES NO

[align=left]Source[/align]
2010 ACM-ICPC Multi-University Training Contest(17)——Host by ZSTU

[align=left]Recommend[/align]
lcy

#include <iostream>
#include <stdio.h>
#include <string.h>
using namespace std;

const int MAXN=400010;
const int MAXM=6000010;
const int INF=99999999;
struct Edge
{
int to,next,cap,flow;
};

struct Ana
{
int state[2000][20];
int flag[2000];
int time[2000];
int cnt;
};

Edge edge[MAXM];
int head[MAXN],tol;
int gap[MAXN],dep[MAXN],pre[MAXN],cur[MAXN];
Ana ana;

void init()
{
tol=0;
memset(head,-1,sizeof(head));
memset(ana.flag,-1,sizeof(ana.flag));
memset(ana.time,0,sizeof(ana.time));
ana.cnt=0;
}

void addedge(int u,int v,int w,int rw=0)
{
edge[tol].to=v;
edge[tol].cap=w;
edge[tol].next=head[u];
edge[tol].flow=0;
head[u]=tol++;
edge[tol].to=u;
edge[tol].cap=rw;
edge[tol].next=head[v];
edge[tol].flow=0;
head[v]=tol++;
}

int sap(int start,int end,int N)
{
memset(gap,0,sizeof(gap));
memset(dep,0,sizeof(dep));
memcpy(cur,head,sizeof(head));
int u=start;
pre[u]=-1;
gap[0]=N;
int ans=0;
while(dep[start]<N)
{
if(u==end)
{
int Min=INF;
for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
if(Min>edge[i].cap-edge[i].flow)
Min=edge[i].cap-edge[i].flow;
for(int i=pre[u];i!=-1;i=pre[edge[i^1].to])
{
edge[i].flow+=Min;
edge[i^1].flow-=Min;
}
u=start;
ans+=Min;
continue;
}
bool flag=false;
int v;
for(int i=cur[u];i!=-1;i=edge[i].next)
{
v=edge[i].to;
if(edge[i].cap-edge[i].flow&&dep[v]+1==dep[u])
{
flag=true;
cur[u]=pre[v]=i;
break;
}
}
if(flag)
{
u=v;
continue;
}
int Min=N;
for(int i=head[u];i!=-1;i=edge[i].next)
if(edge[i].cap-edge[i].flow&&dep[edge[i].to]<Min)
{
Min=dep[edge[i].to];
cur[u]=i;
}
gap[dep[u]]--;
if(!gap[dep[u]])
return ans;
dep[u]=Min+1;
gap[dep[u]]++;
if(u!=start)
u=edge[pre[u]^1].to;
}
return ans;
}

int main()
{
int n,m;
int source,sink;
int tmp;
int stat[20];
int ans;
source=0;
while(~scanf("%d%d",&n,&m))
{
init();

for(int i=0;i<n;i++)
{
ans=0;
for(int j=0;j<m;j++)
{
scanf("%d",&tmp);
ans=ans*2+tmp;
stat[j]=tmp;
}
if(ana.flag[ans]==-1)
{
ana.flag[ans]=ana.cnt;
ana.time[ana.cnt]++;
for(int j=0;j<m;j++)
ana.state[ana.cnt][j]=stat[j];
ana.cnt++;
}
else
{
ana.time[ana.flag[ans]]++;
}
}

sink=ana.cnt+m+1;

for(int i=0;i<ana.cnt;i++)
{
addedge(source,i+1,ana.time[i]);
}

for(int i=0;i<ana.cnt;i++)
{
for(int j=0;j<m;j++)
{
if(ana.state[i][j]!=0)
{
addedge(i+1,ana.cnt+j+1,ana.time[i]);
}
}
}

for(int i=ana.cnt+1;i<=ana.cnt+m;i++)
{
scanf("%d",&tmp);
addedge(i,sink,tmp);
}

ans=(n==sap(source,sink,sink+1));
if(ans)
printf("YES\n");
else
printf("NO\n");

}
}

 

查看原文:http://colorfulshark.cn/wordpress/escape-1032.html
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: