zoj 3642 Just Another Information Sharing Problem

Just Another Information Sharing Problem

Time Limit: 2 Seconds        Memory Limit: 65536 KB

There is going to be another test in the kindergarten. Again the teacher has already told every kid some information about the test in advance. This time, all the children share their information with others. But everyone just share some of his information. The teacher want to know how many information someone can get at most.

Input

There are multiple cases, about 50 cases.
The first line of each case contains an integer n, indicating there are n kids.
The following n lines describe the state of the ith student. "Ai Bi Ci x1 x2 ... xAi". The ith kid has Ai distinct information. The information id is x1x2 ... xAi. He is going to share at least Biinformation and at most Ci information. (0 ≤ Bi ≤ Ci ≤ Ai) When some kid share 0 information with others, he is still in the sharing state, and get the information shared by others(Though he doesn't provide anything).
The next line is a number m. You should find how many information kid m can get at most. (1 ≤ m ≤ n)The index of kids is from 1 to n. 

n is less than 200, and is positive. The information id is among [1,1000000]. There would be 200 distinct information at most.
The number of information each student carry is among [0,10]. Different kids may carry same information.

Each information can be shared by different kids at the same time.
Output

Just output the number of information that student can get at most.

Sample Input
2
2 1 2 3 4
0 0 0
2
2
2 1 1 5 6
1 1 1 5
2
Sample Output
2
2
Hint

Sample 1: kid 1 shares both information, kid 2 shares nothing. kid 2 can have 2 information.
Sample 2: kid 1 shares (6), kid 2 shares (5). Then kid 2 can have 2 information.

 

分析:二分匹配,将人拆成c个点(最小值b是没用的),再从他拥有的信息向这c个点分别建边。注意先排除题目求的人以及他拥有的信息

#include<cstdio>
#include<vector>
#include<cstring>
using namespace std;
const int N=2000;
int match[N],m1[1000001];
bool vis[N],h[200];
vector<int> g[N];
struct Kid{
	int a,b,c,x[10];
}K[200];
bool hungary(int u){
	int i,v,s=g[u].size();
	for(i=0;i<s;i++){
		v=g[u][i];
		if(!vis[v]){
			vis[v]=1;
			if(match[v]==-1||hungary(match[v])){
				match[v]=u;
				return 1;
			}
		}
	}
	return 0;
}
int main(){
	int n,m,y,i,j,k,nf,ans;
	while(~scanf("%d",&n)){
		k=0;memset(m1,-1,sizeof(m1));
		for(i=0;i<n;i++){
			scanf("%d%d%d",&K[i].a,&K[i].b,&K[i].c);
			for(j=0;j<K[i].a;j++){
				scanf("%d",&y);
				if(m1[y]==-1)m1[y]=k++;
				K[i].x[j]=m1[y];
			}
		}
		scanf("%d",&m),m--;
		memset(h,0,sizeof(h));
		for(i=0;i<K[m].a;i++)h[K[m].x[i]]=1;
		nf=k;k=0;
		for(i=0;i<nf;i++)g[i].clear();
		for(i=0;i<n;i++)if(i!=m){
			for(y=0;y<K[i].c;y++){
				for(j=0;j<K[i].a;j++)if(!h[K[i].x[j]]){
					g[K[i].x[j]].push_back(k);
				}
				k++;
			}
		}
		ans=0;
		memset(match,-1,sizeof(match));
		for(i=0;i<nf;i++){
			memset(vis,0,sizeof(vis));
			if(hungary(i))ans++;
		}
		printf("%d\n",ans+K[m].a);
	}
	return 0;
}


 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值