HDU 3605 Escape 网络流最大流 合并点
2016-05-21 09:30
561 查看
表面上看这是一道很明显的网络流题目,只要把源点连到所有人上,每个人再连到星球上,星球再连接到汇点即可,但是由于点数太多导致边数也很多,最终超时。
实际上每个人最多就只有10个星球可以选择,也就是1024种可能,那么只要人数超过1024,必定会出现重复的选择情况,而且重复的次数相当多,如果我们把这些选择相同的人合并起来,并且把对应的边的容量也合并起来,就可以将点缩减至1036个,从而降低时间复杂度。
Problem - 3605
查看原文:http://colorfulshark.cn/wordpress/escape-1032.html
实际上每个人最多就只有10个星球可以选择,也就是1024种可能,那么只要人数超过1024,必定会出现重复的选择情况,而且重复的次数相当多,如果我们把这些选择相同的人合并起来,并且把对应的边的容量也合并起来,就可以将点缩减至1036个,从而降低时间复杂度。
Problem - 3605
[align=center] [/align] |
EscapeTime 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
相关文章推荐
- C#网络编程 (五) 简单端口扫描程序
- 请问人工神经网络中的activation function的作用具体是什么?为什么ReLu要好过于tanh和sigmoid function?
- 图解win7下ping命令使用
- 网络编程,下载视频图片
- Socket小白篇-附加TCP/UDP简介
- IOS 开发不得不知道的网络知识
- 无线网络密码破解
- 网络***那些事
- 快速Android开发系列网络篇之Android-Async-Http
- TCP SYN-Cookie的原理和扩展
- 网络专业名词
- 网络之TCP/IP四层协议
- H3C模拟器---HCL使用心得
- 分布式网络爬虫的基本实现简述
- [javaSE] 网络编程(URLConnection)
- 网络黑客攻防学习平台之基础关第六题
- UNIX网络编程之线程浅析
- 网络黑客攻防学习平台之基础关第五题
- [javaSE] 网络编程(URL)
- POJ 3680 Intervals