zoukankan      html  css  js  c++  java
  • 「网络流24题」 3. 最小路径覆盖问题

    「网络流24题」 3. 最小路径覆盖问题

    <题目链接>


    如题,最小路径覆盖。

    套路拆点,每个点i拆成xi、yi,对于每一条u->v,连xu->yv有向,然后在新图上跑匈牙利。

    最大流也可以做,但匈牙利更简单。

    最后遍历每个x部点,向其匹配点走,沿途标记为已访问。

    已经遍历过的不再遍历。

    二分图相关定理:最小路径覆盖数=点数-最大匹配数。

    #include <cstdio>
    #include <cstring>
    using namespace std;
    const int MAXN=310,MAXM=12010;
    bool vis[MAXN];
    int n,m,cnt,ans,head[MAXN],cx[MAXN],cy[MAXN];
    struct edge
    {
    	int nxt,to;
    }e[MAXM];
    void AddEdge(int x,int y)
    {
    	e[++cnt].nxt=head[x];
    	e[cnt].to=y;
    	head[x]=cnt;
    }
    void AddEdges(int x,int y)
    {
    	AddEdge(x,y);
    	AddEdge(y,x);
    }
    bool DFS(int x)
    {
    	for(int i=head[x],t;i;i=e[i].nxt)
    		if(!vis[t=e[i].to])
    		{
    			vis[t]=1;
    			if(!cy[t] || DFS(cy[t]))
    			{
    				cx[x]=t,cy[t]=x;
    				return 1;
    			}
    		}
    	return 0;
    }
    void Hungary(void)
    {
    	for(int i=1;i<=n;++i)
    		if(!cx[i])
    		{
    			memset(vis,0,sizeof vis);
    			ans-=DFS(i);
    		}
    }
    void Print(int x)
    {
    	x+=n;
    	do
    		printf("%d ",x=x-n);
    	while(vis[x]=1,x=cx[x]);
    	printf("
    ");
    }
    int main(int argc,char *argv[])
    {
    	scanf("%d %d",&n,&m);
    	ans=n;
    	for(int i=1,x,y;i<=m;++i)
    	{
    		scanf("%d %d",&x,&y);
    		AddEdges(x,y+n);
    	}
    	Hungary();
    	memset(vis,0,sizeof vis);
    	for(int i=1;i<=n;++i)
    		if(!vis[i])
    			Print(i);
    	printf("%d
    ",ans);
    	return 0;
    }
    

    谢谢阅读

  • 相关阅读:
    175. Combine Two Tables
    VirtualBox下安装CentOS7系统
    idea配置maven
    idea配置jdk
    SpringBoot在yml中添加自定义配置并识别
    多表联查另一个表的所有
    java后台判断字符串相等 equals
    查询字段内容截取
    idea刷新项目、清除项目缓存
    SpringBoot集成FreeMarker
  • 原文地址:https://www.cnblogs.com/Capella/p/8191594.html
Copyright © 2011-2022 走看看