HDU 3605 Escape(最大流+缩点转换)

http://acm.hdu.edu.cn/showproblem.php?pid=3605

题目很简单,要求的就是最后能搬到星球上去的人的个数。刚开始看到,知道是最大流,就把人和星球都设为点,能生存就连线,权值为1,最后建立超级源点和超级汇点。求出最大流量即可。先是RE,开大数组后TLE。仔细算了,光光人到星球的便就可达到100w了,超时的概率太大了。后来找了解题报告,知道了缩点这一说,因为星球个数m最大只有10个,所以每个人最多只有1024种情况,把这每一种情况设为点(这里很抽象),将之与符合情况的星球相连。边流量就是这种情况总的人数。最后每个星球以限定居住人数为边流量连超级汇点。建图完成后就可以用最大流求解了。

  1 /*Dinic算法求最大流*/
  2 #include<stdio.h>
  3 #include<string.h>
  4 #define point_MAX 100025
  5 #define edge_MAX 10000000
  6 #define INF_MAX 999999999
  7 #include<iostream>
  8 using namespace std;
  9 struct EDGE
 10 {
 11     int to;/*指向的点*/
 12     int next;/*指向的下一条邻边*/
 13     int w;/*权值*/
 14 }edge[edge_MAX];
 15 int len;/*边的数量*/
 16 int point[point_MAX];
 17 int Vertex,Edge;
 18 int d[point_MAX];
 19 void init()/*初始化*/
 20 {
 21     len=0;
 22     memset(point,0,sizeof(point));
 23 }
 24 int add_edge(int a,int b,int w)/*添加由a指向b的权值为w的边*/
 25 {
 26     len++;
 27     edge[len].w=w;
 28     edge[len].to=b;
 29     edge[len].next=point[a];
 30     point[a]=len;
 31     return 0;/*无重边,插入*/
 32 }
 33 int bfs(int s)
 34 {
 35     int q[point_MAX],front=0,rear=1,j,t,i;
 36     q[0]=s;
 37     memset(d,-1,sizeof(d));/**/
 38     d[s]=0;
 39     while(front<rear)
 40     {
 41        t=q[front++];
 42          for(j=point[t];j;j=edge[j].next)
 43          {
 44             if(d[edge[j].to]==-1&&edge[j].w>0)
 45             {
 46              d[edge[j].to]=d[t]+1;
 47            q[rear++]=edge[j].to;/*逐层增加*/
 48         }
 49          }
 50     }
 51     if(d[Vertex]>=0)
 52        return 1;
 53     return 0;
 54 }
 55 long long min(long long a,long long b)
 56 {
 57     return a<b?a:b;
 58 }
 59 long long dinic(int t,long long sum)/*寻找增广路*/
 60 {
 61     int i,os,j;
 62     long long a;
 63     if(t==Vertex)/*如果已经找到汇点,返回sum*/
 64       return sum;
 65     os=sum;
 66     for(i=point[t];i&&sum;i=edge[i].next)
 67     {
 68        if(d[edge[i].to]==d[t]+1&&edge[i].w>0)/*可行流,即增广路*/
 69        {
 70            a=dinic(edge[i].to,min(sum,edge[i].w));
 71            edge[i].w-=a;
 72            for(j=point[edge[i].to];edge[j].to!=t;j=edge[j].next);
 73            edge[j].w+=a;/*处理反向边*/
 74            sum-=a;
 75        }
 76     }
 77     return os-sum;
 78 }
 79 long long DINIC(int s)/*DINIC算法*/
 80 {
 81      long long ans=0;
 82      while(bfs(s))/*遍历整个图,判断是否已经完成最大流*/
 83        ans+=dinic(s,INF_MAX);/*添加所能增加的流量*/
 84      return ans;
 85 }
 86
 87 int main()
 88 {
 89     int n,m,x,a[2005];
 90     int s=0,t=1050;
 91     while(scanf("%d%d",&n,&m)!=EOF)
 92     {
 93         init();
 94         memset(a,0,sizeof(a));
 95         for(int i=1;i<=n;i++)
 96         {
 97             int k=0;
 98             for(int j=0;j<m;j++)
 99             {
100                 scanf("%d",&x);
101                 if(x)
102                 {
103                     k|=1<<j;
104                 }
105             }
106             a[k]++;
107         }
108
109         for(int i=1;i<=(1<<m);i++)
110         {
111             if(a[i-1])
112             {
113                 add_edge(s,i,a[i-1]);
114                 add_edge(i,s,0);
115                 for(int j=0;j<m;j++)
116                     if((i-1)&(1<<j))
117                     {
118                         add_edge(i,j+10+(1<<m),a[i-1]);
119                         add_edge(j+10+(1<<m),i,0);
120                     }
121             }
122         }
123         for(int i=0;i<m;i++)
124         {
125             scanf("%d",&x);
126             add_edge(i+(1<<m)+10,t,x);
127             add_edge(t,i+(1<<m)+10,0);/*添加反向边*/
128
129         }
130         Vertex=t;
131         int ans=DINIC(0);
132         //cout<<ans<<endl;
133         if(ans>=n)cout<<"YES"<<endl;
134         else cout<<"NO"<<endl;
135     }
136     return 0;
137 }

HDU 3605 Escape(最大流+缩点转换)

时间: 2024-10-19 17:53:25

HDU 3605 Escape(最大流+缩点转换)的相关文章

Hdu 3605 Escape (最大流 + 缩点)

题目链接: Hdu 3605  Escape 题目描述: 有n个人要迁移到m个星球,每个星球有最大容量,每个人有喜欢的星球,问是否所有的人都能迁移成功? 解题思路: 正常情况下建图,不会爆内存,但是TLE还是稳稳的.以前只遇到过网络流拆点建图,这个正好是缩点建图.吼吼吼~~~,建图的方式还是值得学习的. 因为星球数目最多十个,那么无论有多少个人,其不同选择也就2^10种咯.把不同的选择作为节点,节点就从10^5减少到了2^10,整整缩小了一个数量级呢.建立源点和汇点,源点和选择链接,边权为这种选

HDU 3605 Escape 最大流+状压

原题链接:http://acm.hdu.edu.cn/showproblem.php?pid=3605 Escape Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 7145    Accepted Submission(s): 1553 Problem Description 2012 If this is the end of the

HDU 3605 Escape (最大流)

Escape Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Description 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

HDU 3605 Escape【二分图多重匹配】

题意: 有n个人去m个星球  告诉你每个人想去哪些星球和每个星球最多容纳多少人,问能不能让所有人都满足 分析: 二分图多重匹配 代码: 1 #include <iostream> 2 #include <cstdio> 3 #include <cstring> 4 #include <vector> 5 using namespace std; 6 7 const int maxn = 100005; 8 const int maxm = 15; 9 10

hdu 3605 Escape (二分图多重匹配)

Escape Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4298    Accepted Submission(s): 1129 Problem Description 2012 If this is the end of the world how to do? I do not know how. But now scient

HDU 3605 Escape(状压+最大流)

Escape Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 9430    Accepted Submission(s): 2234 Problem Description 2012 If this is the end of the world how to do? I do not know how. But now scient

hdu 3605 Escape 二分图的多重匹配(匈牙利算法)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=3605 Escape Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 8001    Accepted Submission(s): 1758 Problem Description 2012 If this is the end of th

HDU 3605 Escape(状态压缩+最大流)

http://acm.hdu.edu.cn/showproblem.php?pid=3605 题意: 有n个人和m个星球,每个人可以去某些星球和不可以去某些星球,并且每个星球有最大居住人数,判断是否所有人都能去这m个星球之中. 思路: 这道题建图是关键,因为n的数量很大,如果直接将源点和人相连,是会超时的,因为m≤10,所以每个人的选择可以用二进制来存储,这样最多也就1<<m-1种状态,相同的就可以放在一起处理了. 1 #include<iostream> 2 #include&l

HDU 3605 —— Escape 状态压缩+最大流

原题:http://acm.hdu.edu.cn/showproblem.php?pid=3605 #include<cstdio> #include<cstring> #include<string> #include<queue> #include<cmath> #include<vector> #include<algorithm> #define inf 1e9 using namespace std; const