首页 > 代码库 > 网络流 HDU 3605

网络流 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 }

 

网络流 HDU 3605