HDU 3605Escape(缩点+网络流之最大流)
生活随笔
收集整理的這篇文章主要介紹了
HDU 3605Escape(缩点+网络流之最大流)
小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.
題目地址:http://acm.hdu.edu.cn/showproblem.php?pid=3605
本來打算昨天寫兩道題的,結(jié)果這個題卡住了,最后才發(fā)現(xiàn)是最后的推斷條件出錯了,推斷滿流的條件應該是與n的比較,居然寫成與全部星球總?cè)萘康谋容^了。(近期大腦短路。。)
這題也不是全然自己想的,沒想到縮點這一技巧,由于n的數(shù)據(jù)范圍太大,普通的建圖方法會超時超內(nèi)存,須要縮點,由于對于每一個點來說,一共僅僅有2^10種方法,而最多一共同擁有10W個點,顯然有非常多點是反復的,這時能夠採取縮點的方法,將反復的當成一個點來處理。這樣數(shù)據(jù)范圍就縮小到了1024個點,速度大大提升。
建圖思路是建一源點與匯點,將每種方法與源點相連,權(quán)值為這樣的方法反復的次數(shù),將每一個星球與匯點相連,權(quán)值為每一個星球的最大容量,再將每種方法與星球相連,權(quán)值為INF,最后推斷是否滿流。
代碼例如以下:
#include <iostream> #include <stdio.h> #include <string.h> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include <map> #include <algorithm>using namespace std; const int INF=1e9; int head[2000], s, t, nv, n, cnt; int num[2000], d[2000], pre[2000], cur[2000], q[2000], fei[2000]; struct node {int u, v, next, cap; }edge[1000000]; void add(int u, int v, int cap) {edge[cnt].v=v;edge[cnt].cap=cap;edge[cnt].next=head[u];head[u]=cnt++;edge[cnt].v=u;edge[cnt].cap=0;edge[cnt].next=head[v];head[v]=cnt++; } void bfs() {memset(num,0,sizeof(num));memset(d,-1,sizeof(d));int f1=0, f2=0, i;q[f1++]=t;d[t]=0;num[0]=1;while(f1>=f2){int u=q[f2++];for(i=head[u];i!=-1;i=edge[i].next){int v=edge[i].v;if(d[v]==-1){d[v]=d[u]+1;num[d[v]]++;q[f1++]=v;}}} } int isap() {memcpy(cur,head,sizeof(cur));int flow=0, i, u=pre[s]=s;bfs();while(d[s]<nv){if(u==t){int f=INF, pos;for(i=s;i!=t;i=edge[cur[i]].v){if(f>edge[cur[i]].cap){f=edge[cur[i]].cap;pos=i;}}for(i=s;i!=t;i=edge[cur[i]].v){edge[cur[i]].cap-=f;edge[cur[i]^1].cap+=f;}flow+=f;if(flow>=n)return flow;u=pos;}for(i=cur[u];i!=-1;i=edge[i].next){if(d[edge[i].v]+1==d[u]&&edge[i].cap){break;}}if(i!=-1){cur[u]=i;pre[edge[i].v]=u;u=edge[i].v;}else{if(--num[d[u]]==0) break;int mind=nv;for(i=head[u];i!=-1;i=edge[i].next){if(mind>d[edge[i].v]&&edge[i].cap){mind=d[edge[i].v];cur[u]=i;}}d[u]=mind+1;num[d[u]]++;u=pre[u];}}return flow; } int main() {int m, x, i, j, top, y, z, num, a[20];while(scanf("%d%d",&n,&m)!=EOF){memset(head,-1,sizeof(head));memset(fei,0,sizeof(fei));cnt=0;s=0;top=0;num=0;for(i=1;i<=n;i++){x=0;for(j=1;j<=m;j++){scanf("%d",&y);x=x*2+y;}fei[x]++;}for(i=1;i<=1100;i++){if(fei[i]){num++;}}t=num+m+1;nv=t+1;for(i=1;i<=1100;i++){if(fei[i]){//printf("--%d %d\n", i, fei[i]);top++;add(s,top,fei[i]);x=i;z=m+1;while(x){y=x%2;z--;if(y){add(top,z+num,INF);}//printf("--%d %d %d %d--",y, top, z, num);x=x/2;}//printf("\n");}}for(i=1;i<=m;i++){scanf("%d",&x);add(i+num,t,x);}x=isap();if(x>=n)printf("YES\n");elseprintf("NO\n");}return 0; }
轉(zhuǎn)載于:https://www.cnblogs.com/gcczhongduan/p/4296425.html
總結(jié)
以上是生活随笔為你收集整理的HDU 3605Escape(缩点+网络流之最大流)的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 浅析数据中心机房工程
- 下一篇: antd table表格删除末页数据,跳