HDU 3605 Escape 最大流or二分圖多重匹配 2010 ACM-ICPC Multi-University Training Contest(17)——Host by ZSTU

 

Escape

Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/32768 K (Java/Others)
Total Submission(s): 1122 Accepted Submission(s): 321


Problem 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 not fit to live some of the planet. Now scientists want your help, is to determine what all of people can live in these planets.

Input
More set of test data, the beginning of each data is n (1 <= n <= 100000), m (1 <= m <= 10) n indicate there n people on the earth, m representatives m planet, planet and people labels are from 0. Here are n lines, each line represents a suitable living conditions of people, each row has m digits, the ith digits is 1, said that a person is fit to live in the ith-planet, or is 0 for this person is not suitable for living in the ith planet.
The last line has m digits, the ith digit ai indicates the ith planet can contain ai people most..
0 <= ai <= 100000

Output
Determine whether all people can live up to these stars
If you can output YES, otherwise output NO.

Sample Input

1 1
1
1

2 2
1 0
1 0
1 1


Sample Output
YES
NO
Source

Recommend
lcy
 
 
一看就是一個網絡流,建圖套上模板提交,RE...
邊算小了,改大變成TLE,然後用盡各種方法還是TLE
開始懷疑不是網絡流了,因爲點太多了。
換成二分圖多重匹配,TLE。。。
杯具的以爲今晚要0AC了(又是一次練習賽)。。。
於是忍不住去搜了一下解題報告,
確實有網絡流解法,不過n=10^6肯定TLE,不過m<=10很小,
那麼所有人的選擇只有2^m種,統計這個2^m中選擇的數量,
這2^m種選擇作爲節點連接到m個星球節點邊權爲統計的數量,
源點s到這些節點邊權同上(我寫的inf一直WA,爲什麼會錯呢),
m個星球節點到匯點t連邊,邊權爲星球容量。
這樣10^6的節點減少到10^3就能不TLE了。
其實下午纔剛做了一道類似的縮小數據範圍的題,怎麼晚上就忘了呢。。。
ACMDIY第二屆羣賽Ahui Writes Word:一個01揹包問題,可是n=100000,v=10000
肯定TLE,不過體積和價值都是《=10,可以把它轉換爲100類物品的多重揹包,
再用二進制壓縮轉換爲01揹包求解。
-------------------------------------------------------------------------------------------------------
本題還可以用二分圖多重匹配解,剛開始把標記數組開大了,導致一直TLE...
標記數組開10就夠了,我弄了個10萬,不超時纔怪。。。
 
還有這個要用C++提交纔不超時,不過可以用輸入外掛G++、C++都非常快
 
最大流代碼:
#include<cstdio>
#include<cstring>
#define N 2005
#define M 30005
#define inf 999999999
#define min(a,b) ((a)<(b)?(a):(b))

int n,m,s,t,num,adj[N],dis[N],q[N];
struct edge
{
	int v,w,pre;
	edge(){}
	edge(int vv,int ww,int p){v=vv;w=ww;pre=p;}
}e[M];
void insert(int u,int v,int w)
{
	e[num]=edge(v,w,adj[u]);
	adj[u]=num++;
	e[num]=edge(u,0,adj[v]);
	adj[v]=num++;
}
int bfs()
{
	int i,x,v,head=0,tail=0;
	memset(dis,0,sizeof(dis));
	dis[s]=1;
	q[++tail]=s;
	while(head!=tail)
	{
		x=q[head=(head+1)%N];
		for(i=adj[x];~i;i=e[i].pre)
			if(e[i].w&&!dis[v=e[i].v])
			{
				dis[v]=dis[x]+1;
				if(v==t)
					return 1;
				q[tail=(tail+1)%N]=v;
			}
	}
	return 0;
}
int dfs(int x,int limit)
{
	if(x==t)
		return limit;
	int i,v,tmp,cost=0;
	for(i=adj[x];~i&&cost<limit;i=e[i].pre)
		if(e[i].w&&dis[x]==dis[v=e[i].v]-1)
		{
			tmp=dfs(v,min(limit-cost,e[i].w));
			if(tmp)
			{
				e[i].w-=tmp;
				e[i^1].w+=tmp;
				cost+=tmp;
			}
			else
				dis[v]=-1;
		}
	return cost;
}
int Dinic()
{
	int ans=0;
	while(bfs())
		ans+=dfs(s,inf);
	return ans;
}
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		int i,j,k,a,w,x[2005]={0};
		memset(adj,-1,sizeof(adj));
		num=0;
		s=0;
		t=2000;
		for(i=0;i<n;i++)
		{
			k=0;
			for(j=0;j<m;j++)
			{
				scanf("%d",&a);
				if(a)
					k|=1<<j;
			}
			x[k]++;
		}
		for(i=0;i<(1<<m);i++)
			if(x[i])
			{
				insert(s,i+1,x[i]);
				for(j=0;j<m;j++)
					if(i&(1<<j))
						insert(i+1,j+10+(1<<m),x[i]);
			}
		for(j=0;j<m;j++)
		{
			scanf("%d",&w);
			insert(j+10+(1<<m),t,w);
		}
		puts(Dinic()>=n?"YES":"NO");
	}
}


二分圖多重匹配代碼:
#include<cstdio>
#include<cstring>
#include<iostream>

int n,m,w[15],cnt[15];
int adj[100010][12],mat[12][100010];
bool f[15];
bool dfs(int x)
{
	int i,j,v;
	for(i=0;i<m;i++)
		if(!f[i]&&adj[x][i])
		{
			f[i]=1;
			if(cnt[i]<w[i])
			{
				mat[i][cnt[i]++]=x;
				return true;
			}
			for(j=0;j<cnt[i];j++)
				if(dfs(mat[i][j]))
				{
					mat[i][j]=x;
					return true;
				}
		}
	return false;
}
bool ok()
{	
	int i;
	memset(cnt,0,sizeof(cnt));
	for(i=0;i<n;i++)
	{
		memset(f,0,sizeof(f));
		if(!dfs(i))
			return false;
	}
	return true;
}
int main()
{
	while(~scanf("%d%d",&n,&m))
	{
		int i,j;
		for(i=0;i<n;i++)
			for(j=0;j<m;j++)
				scanf("%d",&adj[i][j]);
		for(j=0;j<m;j++)
			scanf("%d",&w[j]);
		puts(ok()?"YES":"NO");
	}
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章