zoukankan      html  css  js  c++  java
  • 求出二分图所有可能的匹配边

    pku 1904

    题目大意是有一个国王,他有n个儿子,现在有n个美丽的女子准备嫁给他的n个儿子。国王已经让他的大臣收集了每个儿子喜欢的姑娘的编号(可以喜欢很多个),并且大臣们已经找出了一个完美匹配的方案。现在国王不满意,他想要知道所有可能的匹配方案(前提是每个儿子可以娶到一个姑娘)。即求出每个儿子所有可能的结婚方案。

    这题的解法是:

    1、根据题目信息建图(王子->姑娘)。

    2、根据题目给定的完美匹配建图(姑娘->王子)。

    3、求强连通分量

    4、如果某个姑娘和王子在一个连通分量,并且他们之间在原图上存在直接边,那么这个姑娘便是王子的可能匹配

    分析:

    根据题意,每个王子喜欢的姑娘已经确定了,他只能娶他喜欢的。既然是n个王子,n个姑娘。也就是说,最终最终还是一对一,即每个王子必须要有一个老婆。

    假如某一个王子已经和一个姑娘完美匹配了,现在可能存在其他方案,假如这个方案中,王子a和王子b喜欢的某一个姑娘匹配,那么对于王子b来说,他就少了一个老婆的选择了,那怎么办呢?他就只能再去匹配上一个别的王子的姑娘。一次类推,那么这个王子怎么办呢?很有可能最后一个王子便没有老婆了。如果要避免最后一个王子没有老婆的情况发生,那么他就只能管第一个王子要了,谁让他抢走了别人的姑娘呢。这么一折腾,就形成了一个环,也就是一个强连通分量。也就是说,在一个强连通分量里,王子间是可以相互交换老婆的...那么为什么还要原图存在直接边呢?因为直接边说明王子喜欢这个女孩,如果他要了一个自己不喜欢的,那么别的王子自然会少掉一个喜欢的女孩。这是不道德的~

    下面是代码:

    #include<iostream>
    #include<string>
    #include<stack>
    using namespace std;
    
    typedef struct node
    {
    	int v;
    	struct node *next;
    }node;
    
    node *link[5000];
    node edge[400000];
    int num,n;
    
    void add(int u,int v)
    {
    	edge[num].v=v;
    	edge[num].next=link[u];
    	link[u]=edge+num++;
    }
    
    int find(int u,int v)
    {
    	for(node *p=link[u];p;p=p->next)
    	{
    		if(p->v==v)
    			return 1;
    	}
    	return -1;
    }
    
    int dnf[5000],low[5000],instack[5000],belong[5000];
    int cut,mm;
    stack<int>Q;
    
    void tarjan(int u)
    {
    	low[u]=dnf[u]=++mm;
    	instack[u]=1;
    	Q.push(u);
    	for(node *p=link[u];p;p=p->next)
    	{
    		if(!dnf[p->v])
    		{
    			tarjan(p->v);
    			if(low[u]>low[p->v])
    			{
    				low[u]=low[p->v];
    			}
    		}
    		else if(instack[p->v] && low[u]>dnf[p->v])
    		{
    			low[u]=dnf[p->v];
    		}
    	}
    	int v;
    	if(low[u]==dnf[u])
    	{
    		cut++;
    		do
    		{
    			v=Q.top();
    			Q.pop();
    			instack[v]=0;
    			belong[v]=cut;
    		}while(u!=v);
    	}
    }
    
    void solve()
    {
    	cut=0;
    	mm=0;
    	memset(instack,0,sizeof(instack));
    	memset(dnf,0,sizeof(dnf));
    	for(int i=1;i<=2*n;i++)
    	{
    		if(!dnf[i])
    			tarjan(i);
    	}
    }
    
    int main()
    {
    	int i,j,k,a;
    	freopen("D:\\in.txt","r",stdin);
    	while(scanf("%d",&n)!=EOF)
    	{
    		memset(link,0,sizeof(link));
    		num=0;
    		for(i=1;i<=n;i++)
    		{
    			scanf("%d",&k);
    			for(j=1;j<=k;j++)
    			{
    				scanf("%d",&a);
    				add(i,a+n);
    			}
    		}
    		for(i=1;i<=n;i++)
    		{
    			scanf("%d",&a);
    			add(a+n,i);
    		}
    		solve();
    		int ans[2001];
    		for(i=1;i<=n;i++)
    		{
    			k=0;
    			for(j=n+1;j<=2*n;j++)
    			{
    				if(belong[i]==belong[j] && find(i,j)!=-1)
    				{
    					ans[k++]=j-n;	
    				}
    			}
    			printf("%d",k);
    			for(j=0;j<k;j++)
    			{
    				printf(" %d",ans[j]);
    			}
    			printf("\n");
    		}
    	}
    	return 0;
    }
    
  • 相关阅读:
    pytorch——nn.Module
    jQuery性能优化的28个建议
    javascript string 转 date
    javascript 追加date format属性。
    javascript翻页小控件paginator
    getTime()的00:00:00问题。
    禁止输入表情的方法
    解决带有导航的情况下 关于present自动返回的问题
    设置透明色
    class can not be find with platformType:1 step 1
  • 原文地址:https://www.cnblogs.com/ka200812/p/2122013.html
Copyright © 2011-2022 走看看