zoukankan      html  css  js  c++  java
  • UVA 11419 SAM I AM

    The world is in great danger!! Mental’s forces have returned to
    Earth to eradicate humankind. Our last hope to stop this great
    evil is Sam “Serious” Stone. Equipped with various powerful
    weapons, Serious Sam starts his mission to destroy the forces of
    evil.
    After fighting two days and three nights, Sam is now in front of
    the temple KOPTOS where Mental’s general Ugh Zan III is waiting
    for him. But this time, he has a serious problem. He is in shortage
    of ammo and a lot of enemies crawling inside the temple waiting
    for him. After rounding the temple Sam finds that the temple is
    in rectangle shape and he has the locations of all enemies in the
    temple.
    All of a sudden he realizes that he can kill the enemies without entering the temple using the great
    cannon ball which spits out a gigantic ball bigger than him killing anything it runs into and keeps on
    rolling until it finally explodes. But the cannonball can only shoot horizontally or vertically and all the
    enemies along the path of that cannon ball will be killed.
    Now he wants to save as many cannon balls as possible for fighting with Mental. So, he wants to
    know the minimum number of cannon balls and the positions from which he can shoot the cannonballs
    to eliminate all enemies from outside that temple.

    题目大意:
    大小为R*C的网格图中存在一些点需要被打掉,每次可以选择打掉任意一行或任意一列,求最小的步数将所有的点都打掉,并输出方案

    解题报告:
    这题是一个简单的二分图最小点覆盖问题,显然如果每一条边对应一个网格图中的一个点的话,那么答案就是用最小的点去覆盖所有的边
    考虑输出方案:
    设左右两图分别为X,Y 我们选择X中未匹配的点去遍历他的出边,显然这样做答案就是X集合中未标记的点,Y集合中标记了的点,至于为什么Y中标记的点就是答案:因为假设X集合中a未被匹配,那么它所对应的出边就没有被覆盖,所以它的另外一边必然存在于最大匹配中

    #include <algorithm>
    #include <iostream>
    #include <cstdlib>
    #include <cstring>
    #include <cstdio>
    #include <cmath>
    #define RG register
    #define il inline
    #define iter iterator
    #define Max(a,b) ((a)>(b)?(a):(b))
    #define Min(a,b) ((a)<(b)?(a):(b))
    using namespace std;
    const int N=2005,M=1000005;
    int head[N],to[M<<1],nxt[M<<1],n,m,k,bel[N],num=0;bool vis[N],v[N];
    void link(int x,int y){
    	nxt[++num]=head[x];to[num]=y;head[x]=num;
    }
    int gi(){
    	int str=0;char ch=getchar();
    	while(ch>'9' || ch<'0')ch=getchar();
    	while(ch>='0' && ch<='9')str=(str<<1)+(str<<3)+ch-48,ch=getchar();
    	return str;
    }
    bool dfs(int x){
    	int u;v[x]=true;
    	for(int i=head[x];i;i=nxt[i]){
    		u=to[i];if(vis[u])continue;
    		vis[u]=true;
    		if(!bel[u] || dfs(bel[u])){
    			bel[u]=x;bel[x]=u;
    			return true;
    		}
    	}
    	return false;
    }
    void Clear(){
    	memset(head,0,sizeof(head));num=0;
    	memset(bel,0,sizeof(bel));
    }
    void work()
    {
    	Clear();
    	int x,y;
    	for(int i=1;i<=k;i++){
    		x=gi();y=gi();
    		link(x,y+n);link(y+n,x);
    	}
    	int ans=0;
    	for(int i=1;i<=n+m;i++){
    		if(!bel[i]){
    			memset(vis,0,sizeof(vis));
    			ans+=dfs(i);
    		}
    	}
    	printf("%d",ans);
    	memset(vis,0,sizeof(vis));
    	memset(v,0,sizeof(v));
    	for(int i=1;i<=n;i++)
    		if(!bel[i])dfs(i);
    	for(int i=1;i<=n;i++)
    		if(!v[i])printf(" r%d",i);
    	for(int i=1;i<=n;i++){
    		if(vis[i+n])printf(" c%d",i);
    	}
    	puts("");
    }
    
    int main()
    {
    	while(~scanf("%d%d%d",&n,&m,&k)){
    		if(n+m+k==0)break;
    		work();
    	}
    	return 0;
    }
    
  • 相关阅读:
    Android Virtual Device(AVD)屏幕大小调整
    修改obj三维模型文件中坐标z为其相反数
    AE安装检测(C++)
    单件模式
    地形转立体实验截图
    保持几何特征的三维建筑物模型简化方法 毕业硕士论文
    判断多边形点串存放序列
    mathematica 查找 mathpass 注册文件位置
    在线调色板搜集
    图标资源搜集
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7489717.html
Copyright © 2011-2022 走看看