zoukankan      html  css  js  c++  java
  • 「专题训练」Air Raid(HDU-1151)

    题目

    在一个城市里有(n)个地点和(k)条道路,道路是无环的(也就是说一定可以二分染色——回路长度为偶数0),现在伞兵需要去n个地点视察,只能沿着路的方向走,问最少需要多少伞兵。

    分析

    这是什么问题?找出最少的边,访问所有的点——二分图的的最小路径覆盖。
    那么对于一个最大匹配,它能覆盖(2最大匹配)个点,剩下的点都需要单独一条边覆盖,从而设匹配数为(k),覆盖数为(p),有$$n-2k+k=p$$,也就是(n-k=p)

    代码

    #include <cstring>
    #include <algorithm>
    #include <vector>
    #define MP make_pair
    #define PB push_back
    #define fi first
    #define se second
    #define ZERO(x) memset((x), 0, sizeof(x))
    #define ALL(x) (x).begin(),(x).end()
    #define rep(i, a, b) for (int i = (a); i <= (b); ++i)
    #define per(i, a, b) for (int i = (a); i >= (b); --i)
    #define QUICKIO                  
        ios::sync_with_stdio(false); 
        cin.tie(0);                  
        cout.tie(0);
    #define MS(x,y) memset(x,y,sizeof(x))
    using namespace std;
    
    bool mat[125][125],vis[125];
    int n,m;
    int link[125];
    
    bool dfs(int x)
    {
    	rep(i,1,n)
    	{
    		if(mat[x][i] && !vis[i])
    		{
    			vis[i]=true;
    			if(link[i]==-1 || dfs(link[i]))
    			{
    				link[i]=x;
    				return true;
    			}
    		}
    	}
    	return false;
    }
    
    int hungary()
    {
    	int ans=0;
    	rep(i,1,n)
    	{
    		ZERO(vis);
    		if(dfs(i)) ans++;
    	}
    	return ans;
    }
    
    int main()
    {
    	int T; scanf("%d",&T);
    	while(T--)
    	{
    		scanf("%d%d",&n,&m);
    		ZERO(mat);
    		ZERO(vis);
    		MS(link,-1);
    		rep(i,1,m)
    		{
    			int a,b;
    			scanf("%d%d", &a, &b);
    			if(a && b) mat[a][b]=1;
    		}
    		printf("%d
    ", n-hungary());
    	}
    	return 0;
    }
    
    如非注明,原创内容遵循GFDLv1.3发布;其中的代码遵循GPLv3发布。
  • 相关阅读:
    pm2日志切割
    PM2常用命令
    Linux安装nodejs
    npm 修改源地址
    nodejs 生成验证码
    shell脚本解析json文件
    mysql添加用户并赋予权限命令
    Redis 配置密码
    JavaScript也是黑客技术?
    angular和vue的对比学习之路
  • 原文地址:https://www.cnblogs.com/samhx/p/HDU-1151.html
Copyright © 2011-2022 走看看