HDU -- 3605 Escape(最大流 状态合并判满流)
来源:互联网 发布:淘宝退款申请撤销不了 编辑:程序博客网 时间:2024/06/04 18:16
题目大意:
有n个人,m个星球,对每个人来说,每个星球的选取状态可以使选或者不选,每个星球最多住的人数是一定的,问能否所有人都居住在星球上;
思路分析:
最大流判满流,但由于n太大,直接建图最后会超时;
①:一种建图方式是:星球最多有10个,所以每个人对于所有星球最多有2^10个状态,也就是1024个,这样我们就是把十万个点缩成了1024个点,然后我们把相同状态的点进行合并,设立一源点,让源点连向这些状态点,权值为该状态下的人数;设立一个汇点,让所有的星球连向汇点,权值为该星球可居住的人数;最后在状态和在该状态下可以选择的星球之间连边,权值为该状态下的人数,时间为904ms(加了输入外挂);
②:另一种建图的方法也是把相同的状态合并,不过此时使用map存储的每一种状态而已,时间为624ms;
代码实现:
二进制:
#include<cstdio>#include<cstring>#include<queue>#include<iostream>#define Max(a,b) ((a)>(b)?(a):(b))//#pragma comment(linker, "/STACK:1024000000,1024000000")using namespace std;const int N=2000;const int M=325600;const int INF=0x3f3f3f3f;int n,m,s,t,top,head[N],gap[N],cur[N],pre[N],dis[N],state[N],vis[N];struct Edge{ int to,next,flow;}edge[M];void Addedge(int from,int to,int val){ edge[top].to=to,edge[top].next=head[from],edge[top].flow=val,head[from]=top++; edge[top].to=from,edge[top].next=head[to],edge[top].flow=0,head[to]=top++;}void Bfs(){ queue<int> q; memset(gap,0,sizeof(gap)); memset(dis,-1,sizeof(dis)); memset(vis,0,sizeof(vis)); gap[0]=1,dis[t]=0; q.push(t); vis[t]=1; while(!q.empty()){ int u=q.front(); q.pop(); for(int i=head[u];i+1;i=edge[i].next){ if(vis[edge[i].to]==0&&dis[edge[i].to]==-1){ dis[edge[i].to]=dis[u]+1; gap[dis[edge[i].to]]++; q.push(edge[i].to); vis[edge[i].to]=1; } } }}int Sap(){ Bfs(); memset(pre,-1,sizeof(pre)); for(int i=0;i<=t;++i) cur[i]=head[i]; int u=s,i,cur_flow,max_flow=0,neck,tmp; while(dis[s]<=t){ if(u==t){ cur_flow=INF; for(int i=s;i!=t;i=edge[cur[i]].to){ if(cur_flow>edge[cur[i]].flow){ neck=i; cur_flow=edge[cur[i]].flow; } } for(int i=s;i!=t;i=edge[cur[i]].to){ tmp=cur[i]; edge[tmp].flow-=cur_flow; edge[tmp^1].flow+=cur_flow; } max_flow+=cur_flow; u=neck; } int i; for(i=cur[u];i!=-1;i=edge[i].next) if(edge[i].flow&&dis[u]==dis[edge[i].to]+1) break; if(i!=-1){ cur[u]=i; pre[edge[i].to]=u; u=edge[i].to; }else{ if(--gap[dis[u]]==0) break; cur[u]=head[u]; int mindis=t; for(i=head[u];i!=-1;i=edge[i].next){ if(edge[i].flow&&mindis>dis[edge[i].to]) mindis=dis[edge[i].to]; } dis[u]=mindis+1; gap[dis[u]]++; if(u!=s) u=pre[u]; } } return max_flow;}template<class T>inline bool Read(T &n){ T x=0; char c=getchar(); while((c<'0'||c>'9')&&c!=EOF) c=getchar(); if(c==EOF) return false; while(c>='0'&&c<='9') x*=10,x+=(c-'0'),c=getchar(); n=x; return true;}int main(){ while(Read(n)&&Read(m)){ memset(head,-1,sizeof(head)); memset(state,0,sizeof(state)); int f,tmp=(1<<m); top=0,s=tmp+m,t=s+1; for(int i=1;i<=n;++i){ int sum=0; for(int j=1;j<=m;++j){ Read(f); sum=(sum<<1)+f; } state[sum]++;//记录这种状态下的状态数; } for(int i=0;i<tmp;++i){ Addedge(s,i,state[i]);// 源点连向每一种状态; int z=i; int cnt=0; while(z){ if(z&1) Addedge(i,cnt+tmp,state[i]);//在这个状态下可以选cnt对应的星球,就连边; z=z>>1; cnt++; } } for(int i=0;i<m;++i){ Read(f); Addedge(tmp+i,t,f);// 每一个星球连向汇点; } int res=Sap(); if(res==n) printf("YES\n"); else printf("NO\n"); }}
map建图:
map<string,int> mp;map<string,int>::iterator ite;。。。。。。int main(){ while(~scanf("%d%d",&n,&m)){ memset(head,-1,sizeof(head)); top=0; mp.clear(); getchar(); char st[N]; for(int i=0;i<n;++i){ gets(st); string str=st; mp[st]++; } for(int i=0;i<m;++i) scanf("%d",&num[i]); s=0,t=mp.size()+m+1; int i; for(ite=mp.begin(),i=1;ite!=mp.end();++ite,++i){ Addedge(s,i,ite->second); int tmp=1; for(int j=0;j<ite->first.size();++j){ if(ite->first[j]=='1') Addedge(i,mp.size()+tmp,ite->second); if(ite->first[j]=='0'||ite->first[j]=='1') tmp++; } } for(int i=0;i<m;++i) Addedge(i+mp.size()+1,t,num[i]); int res=Sap(); if(res>=n) printf("YES\n"); else printf("NO\n"); }}
0 0
- HDU -- 3605 Escape(最大流 状态合并判满流)
- HDU 3605 Escape(最大流+合并相同点)
- HDU 3605 Escape(最大流+合并点)
- HDU 3605 Escape(最大流+状态压缩)
- hdu 3605 Escape 状态压缩+最大流
- HDU 3605 Escape(最大流+状态压缩)
- HDU 3605 Escape(最大流+状态压缩)
- hdu 3605 Escape (最大流+状态压缩)
- HDU - 3605 Escape(最大流+状态压缩)
- HDU 3605 Escape 网络流最大流 合并点
- hdu 3605 Escape【图论-网络流-最大流-状态压缩】
- HDU 3605 —— Escape 状态压缩+最大流
- hdu 3605 Escape【状态压缩+最大流Dinic+建图】
- hdu 3605 /状态合并最大流
- HDU-3605-Escape(最大流+状压)
- hdu 3605 Escape(最大流+状态压缩 or 二分图多重匹配)
- HDU 3605 Escape 最大流
- HDU 3605 Escape 最大流
- leetoj Remove Duplicates from Sorted Array
- C语言实现IP地址字符串转化成数值地址(双字)
- IT上的本地化理解
- 个人关于JAVA异常的心得
- 【数据可视化】大规模多变量空间数据场可视化2
- HDU -- 3605 Escape(最大流 状态合并判满流)
- stanford parser 使用说明
- hdu 4495 - Rectangle(hash+二分+dp)
- python3自带web服务器
- 异常分析
- 黑马程序员——高新技术---Java基础—常用类—Stirng类,StringBuffer类
- Java学习笔记
- R.java 文件的错误
- Linux 常用命令(2)