• zoj 1525 Air Raid 有向无环图的最小路径覆盖(匹配)


    题目大意:先解释有向无环图的路径覆盖,在图中找一些不相交的简单路径,使之覆盖图中所有顶点,且每一顶点只有一条路径与之关联,也就是说,若沿着这些路径中每条路径从起点走到终点,则可以恰好经过图中每一个顶点一次且仅一次。该题是求最小路径覆盖,即使得路径条数最小。

    题中的限制在顶点,将图转换为二分图,每个顶点v拆为v*和v**,若在图中存在从u到v的有向边,则在二分图中连接一条从u*到v**的边。则有公式:最小路径覆盖数=节点数n-该二分图匹配数。

    现在来证明:在原图中先选择所有顶点,若在二分图中添加一条匹配边<v*,u**>,则v与u被并到了一条路径上,所以路径覆盖数可以减少1,继续添加,直到不存在匹配边为止,因此,二分图上的每条匹配边与原图的路径上的某条有向边对应,相反,对于原图的路径上的每条边,对应到二分图上也组成一个匹配,若不是匹配,则存在某顶点与多条边关联,不符合路径覆盖定义。

    #include <stdio.h>
    #include <string.h>
    #define N 500
    int g[N][N],mk[N],cx[N],cy[N];
    int ans,n;
    
    int path(int u)
    {
    	int i;
    	for(i=1;i<=n;i++)
    	{
    		if(g[u][i]&&!mk[i])
    		{
    			mk[i]=1;
    			if(cy[i]==-1||path(cy[i]))
    			{
    				cx[u]=i;
    				cy[i]=u;
    				return 1;
    			}
    		}
    	}
    	return 0;
    }
    
    void solve()
    {
    	int i;
    	memset(cx,-1,sizeof(cx));
    	memset(cy,-1,sizeof(cy));
    	for(i=1;i<=n;i++)
    		if(cx[i]==-1)
    		{
    			memset(mk,0,sizeof(mk));
    			ans+=path(i);
    		}
    }
    
    int main()
    {
    	int i,x,y,t,m;
    	scanf("%d",&t);
    	while(t--)
    	{
    		ans=0;
    		scanf("%d",&n);
    		scanf("%d",&m);
    		memset(g,0,sizeof(g));
    		for(i=1;i<=m;i++)
    		{
    			scanf("%d%d",&x,&y);
    			g[x][y]=1;
    		}
    		solve();
    		printf("%d
    ",n-ans);
    	}
    	return 0;
    }
    
    


     

  • 相关阅读:
    Android源码剖析之Framework层进阶版(Wms窗口管理)
    如何让项目中的代码更易于维护
    Android源码剖析之Framework层实战版(Ams管理Activity启动)
    node.js学习路线图
    让你的公众号拥有AI能力--微信对话开放平台
    Android跨平台投屏软件(无需root)--scrcpy
    微信H5支付申请相关问题
    Bmob后端云实现无后端开发APP
    微信公众号申请相关问题
    iOS企业包下载安装
  • 原文地址:https://www.cnblogs.com/vermouth/p/3710196.html
Copyright © 2020-2023  润新知