网络流 HDU 3605

建图   源点    ->   1024类人   ->   星球   ->     汇点

权             每类人数目       星球容量     星球容量

列举 0~1024  一位是1 那么和对应的星球建边

  1 #include<stdio.h>
  2 #include<algorithm>
  3 #include<string.h>
  4 #include<queue>
  5 #include<math.h>
  6
  7 using namespace std;
  8 #define inf 100000000
  9 int z[2000];
 10 int vis[5000];
 11 int head[2000];
 12 int y[15];
 13 int cnt,S,T;
 14 struct edg
 15 {
 16     int w,next,to;
 17
 18 }x[50000];
 19 void add(int u,int v,int w)
 20 {
 21     x[cnt].next=head[u];
 22     x[cnt].to=v;
 23     x[cnt].w=w;
 24     head[u]=cnt++;
 25 }
 26 int bfs()
 27 {
 28     memset(vis,-1,sizeof(vis));
 29     queue<int>q1;
 30     q1.push(S);
 31     vis[S]=0;
 32     int j;
 33
 34     while(!q1.empty())
 35     {
 36         int now=q1.front();
 37         q1.pop();
 38         for(j=head[now];j!=-1;j=x[j].next)
 39         {
 40             if(vis[x[j].to]<0&&x[j].w)
 41             {
 42
 43                 vis[x[j].to]=vis[now]+1;
 44                 q1.push(x[j].to);
 45             }
 46         }
 47     }
 48     return vis[T]!=-1;
 49 }
 50 int dfs(int u,int w)
 51 {
 52     int ans=0;
 53
 54     if(u==T)
 55         return w;
 56     int j;
 57     for(j=head[u];j!=-1;j=x[j].next)
 58     {
 59         if(vis[x[j].to]==vis[u]+1&&x[j].w)
 60         {
 61
 62             int b=dfs(x[j].to,min(w-ans,x[j].w));
 63             ans=ans+b;
 64             x[j].w-=b;
 65             x[j^1].w+=b;
 66         }
 67     }
 68     return ans;
 69 }
 70 int main()
 71 {
 72     int n,m;
 73
 74     while(scanf("%d%d",&n,&m)!=EOF)
 75     {
 76         int i,j;
 77         memset(z,0,sizeof(z));
 78
 79         for(i=1;i<=n;i++)
 80         {
 81             int b=0;
 82
 83             for(j=1;j<=m;j++)
 84             {
 85                 int a;
 86                 scanf("%d",&a);
 87                 if(a==1)b=b+(1<<(j-1));
 88             }
 89             z[b]++;
 90         }
 91         for(i=1;i<=m;i++)
 92             scanf("%d",&y[i]);
 93         S=1500;
 94         T=1501;  //这2个点只要没用过就行
 95         cnt=0;
 96         memset(head,-1,sizeof(head));
 97         for(i=0;i<=1024;i++)
 98         {
 99             if(z[i])
100             {
101                 add(S,i,z[i]);
102                 add(i,S,0);
103             }
104         }
105
106         //0 1024  人的下标  1025 1035 星球下标
107         for(i=0;i<=1024;i++)
108         {
109             if(z[i])
110             {
111                 for(j=1;j<=m;j++)
112                 {
113                     if(1<<(j-1)&i)
114                     {
115                         add(i,1024+j,y[j]);
116                         add(1024+j,i,0);
117                     }
118                 }
119             }
120         }
121
122         for(j=1;j<=m;j++)
123         {
124             add(1024+j,T,y[j]);
125             add(T,1024+j,0);
126         }
127
128         int ans=0;
129         while(bfs())
130             ans+=dfs(S,inf);
131         if(ans>=n)
132             printf("YES\n");
133         else
134             printf("NO\n");
135     }
136
137     return 0;
138 }
时间: 2024-12-11 12:07:47

网络流 HDU 3605的相关文章

Hdu 3605 Escape (最大流 + 缩点)

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

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 3549 Flow Problem

网络流 HDU 3549 Flow Problem 题目:http://acm.hdu.edu.cn/showproblem.php?pid=3549 用增广路算法进行求解,注意的问题有两个: 1. 每次增广的时候,反向流量也要进行更行,一开始没注意,WA了几次 ORZ 2. 对于输入的数据,容量要进行累加更新. // 邻接矩阵存储 #include <bits/stdc++.h> using namespace std; const int INF = 0x7fffffff; const i

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 /状态合并最大流

题意:N个人去m个星球,给出n个人可以去哪些星球的01矩阵.求是否能满足所有人都去.(n到10万,m<=10) 一看,起先一瞬间就建图,准备秒了,人向星球连边,直接最大流判断是否为n,提交超时...是啊,10W*10=100W条边,铁定超时.. 后来经牛提示:注意,m<10!  人的可以去星球,一共最多有10个,那只有 2^10次种情况,就是说x部与Y部连线情况很多点是一样的(所给的01矩阵,最多10W行,10列,必然有很多行是一样的).所以X部只留1024个点,这些点中,点i含j个人的状态,

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

http://acm.hdu.edu.cn/showproblem.php?pid=3605 题目很简单,要求的就是最后能搬到星球上去的人的个数.刚开始看到,知道是最大流,就把人和星球都设为点,能生存就连线,权值为1,最后建立超级源点和超级汇点.求出最大流量即可.先是RE,开大数组后TLE.仔细算了,光光人到星球的便就可达到100w了,超时的概率太大了.后来找了解题报告,知道了缩点这一说,因为星球个数m最大只有10个,所以每个人最多只有1024种情况,把这每一种情况设为点(这里很抽象),将之与符

hdu 3605 网络流 状态压缩

/*Author :usedrose */ /*Created Time :2015/8/27 1:45:04*/ /*File Name :2.cpp*/ #pragma comment(linker, "/STACK:1024000000,1024000000") #include <cstdio> #include <iostream> #include <algorithm> #include <sstream> #include

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