您的位置:首页 > 其它

Escape HDU - 3605

2017-10-21 13:00 211 查看
点击打开链接

有10^5个人 会超时间 但只有10个星球 可以进行状态压缩(T了两次看了博客才知道..)

假设有5个星球 对于某一个人 他只去 0 和 3 星球 那他的状态就是 1 0 0 1 0 当做二进制压缩后表示就是 2^0+2^3=9

(对于每一个星球 只能选择去或不去 即为1或0 如此这个状态就唯一对应一个二进制数 而这个二进制数与该状态也是唯一对应的)

这样10^5个点就减少为2^10个点 跑模板即可

#include <bits/stdc++.h>
using namespace std;
#define N 0x3f3f3f3f

struct node
{
int v;
int w;
int next;
};

node edge[50010];
int bit[2000],plant[15],first[2000];
int dis[2000],gap[2000],cur[2000],pre[2000];
int n,m,num,ss,ee,ans;

void addedge(int u,int v,int w);
void build();
void bfs();
void isap();

int main()
{
int i,j,t,sum;
while(scanf("%d%d",&n,&m)!=EOF)
{
memset(bit,0,sizeof(bit));
for(i=1;i<=n;i++)
{
sum=0;
for(j=0;j<m;j++)
{
scanf("%d",&t);
sum+=t*(1<<j);
}
bit[sum]++;
}
for(i=0;i<m;i++)
{
scanf("%d",&plant[i]);
}
build();
isap();
if(ans==n) printf("YES\n");
else printf("NO\n");
}
return 0;
}

void addedge(int u,int v,int w)
{
edge[num].v=v;
edge[num].w=w;
edge[num].next=first[u];
first[u]=num++;
return;
}

void build()
{
int pre[15];
int i,j,t,cnt;

memset(first,-1,sizeof(first));
num=0,ss=(1<<m)+m,ee=(1<<m)+m+1;

for(i=1;i<(1<<m);i++)
{
if(bit[i]>0)
{
memset(pre,0,sizeof(pre));
t=i,cnt=0;
while(t>0)
{
pre[cnt++]=t%2;
t/=2;
}
for(j=0;j<m;j++)
{
if(pre[j]==1)
{
addedge(i,(1<<m)+j,bit[i]);
addedge((1<<m)+j,i,0);
}
}
}
}

for(i=1;i<(1<<m);i++)
{
addedge(ss,i,bit[i]);
addedge(i,ss,0);
}
for(i=0;i<m;i++)
{
addedge((1<<m)+i,ee,plant[i]);
addedge(ee,(1<<m)+i,0);
}

return;
}

void bfs()
{
queue <int> que;
int i,u,v;
memset(dis,-1,sizeof(dis));
memset(gap,0,sizeof(gap));
que.push(ee);
dis[ee]=0;
while(!que.empty())
{
u=que.front();
que.pop();
gap[dis[u]]++;
for(i=first[u];i!=-1;i=edge[i].next)
{
v=edge[i].v;
if(dis[v]==-1)
{
que.push(v);
dis[v]=dis[u]+1;
}
}
}
return;
}

void isap()
{
int j,u,v,w,flow,minn;
bfs();
memcpy(cur,first,sizeof(first));
memset(pre,-1,sizeof(pre));
ans=0,u=ss,flow=N,num=(1<<m)+m+1;
while(dis[ss]<num)
{
int &i=cur[u];
for(;i!=-1;i=edge[i].next)
{

4000
v=edge[i].v,w=edge[i].w;
if(dis[v]+1==dis[u]&&w>0)
{
pre[v]=i;
u=v,flow=min(flow,w);
if(u==ee)
{
while(u!=ss)
{
edge[pre[u]].w-=flow;
edge[pre[u]^1].w+=flow;
u=edge[pre[u]^1].v;
}
ans+=flow,flow=N;
}
break;
}
}
if(i==-1)
{
if(--gap[dis[u]]==0) break;
cur[u]=first[u];
minn=num-1;
for(j=first[u];j!=-1;j=edge[j].next)
{
v=edge[j].v,w=edge[j].w;
if(w>0)
{
minn=min(minn,dis[v]);
}
}
dis[u]=minn+1;
gap[dis[u]]++;
if(u!=ss)
{
u=edge[pre[u]^1].v;
}
}
}
return;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: