HDU3605,最大流,狀態壓縮
阿新 • • 發佈:2018-12-13
題目連結:Escape 二分圖的多重匹配,有最大流做的。如果按照普通的最大流建圖,會TLE,這裡考慮到m的範圍是0-10,故用二進位制狀態壓縮,最多也就2^10多種可能。 詳見程式碼:
/************************************************************************* > File Name: main.cpp > Author:Eagles > Mail:None > Created Time: 2018年10月05日 星期五 14時59分11秒 > Description:HDU3605 ************************************************************************/ #include<iostream> #include<cstdio> #include<cmath> #include<cstring> #include<algorithm> #include<vector> #include<stack> #include<bitset> #include<cstdlib> #include<set> #include<list> #include<deque> #include<map> #include<queue> using namespace std; #define N 1000000 struct node { int to; int nex; int val; }E[N]; int n,m,cnt; int head[N],lev[N]; int S,T; int press[2000]; int plant[10]; void addEdge(int a, int b, int val) { E[cnt].to=b; E[cnt].val=val; E[cnt].nex=head[a]; head[a]=cnt++; E[cnt].to=a; E[cnt].val=0; E[cnt].nex=head[b]; head[b]=cnt++; } bool bfs() { memset(lev,0,sizeof(lev)); queue<int>q; q.push(S); lev[S]=1; while (!q.empty()) { int u=q.front(); q.pop(); for (int i=head[u]; i!=-1; i=E[i].nex) { int v=E[i].to; if (E[i].val > 0 &&lev[v]==0) { lev[v]=lev[u]+1; q.push(v); if (v==T) return true; } } } return false; } int dfs(int u, int f) { if (u == T) return f; int tag=0; for (int i=head[u]; i!=-1; i=E[i].nex) { int v=E[i].to; if (E[i].val>0&&lev[v]==lev[u]+1) { int d=dfs(v,min(f-tag,E[i].val)); E[i].val-=d; E[i^1].val+=d; tag+=d; if (tag == f) return f; } } return tag; } int Dinic() { int ans=0; int inf=1000000; while (bfs()) { ans+=dfs(S,inf); } return ans; } void init() { memset(head,-1,sizeof(head)); memset(press,0,sizeof(press)); cnt=0; S=(1<<m+1)+m; T=S+1; for (int i=0; i<n; i++) { int tmp=0; for (int j=0; j<m; j++) { int a; scanf("%d",&a); tmp+=(1<<j)*a; } press[tmp]++; } for (int i=0; i<m; i++) { scanf("%d",&plant[i]); } for (int i=0; i<(1<<m); i++) { if (press[i] != 0) { addEdge(S,i,press[i]); int tmp=i; for (int j=0; j<m; j++) { int a=tmp&1; if (a==1) addEdge(i,(1<<m)+j,press[i]); tmp=tmp>>1; } } } for (int j=0; j<m; j++) addEdge((1<<m)+j,T,plant[j]); } bool check() { init(); int ans=Dinic(); if (ans == n) return true; else return false; } int main() { while (~scanf("%d%d",&n,&m)) { printf("%s\n",check()?"YES":"NO"); } return 0; }