POJ 3041 Asteroids
来源:互联网 发布:ai软件怎么使用 编辑:程序博客网 时间:2024/06/08 11:01
次元传送门
题目大意:
有一个n*n的棋盘,给出一些点的位置,询问最少去掉多少行和列,可以把所有点去掉,输出行列总数
分析:
这道题,棋盘,点,行,列,有没有想到什么??
没错
二分图………….
最大匹配………..
很惭愧(⊙﹏⊙)b,自己太弱了,对二分图理解不够深刻,没看出来这是个二分图>_<,在YOUSIKI童鞋的友情提示下才知道此题要用二分图解(ˇˍˇ) …………….
所以接下来就要说一说怎么求二分图最大匹配
锵锵锵锵!!!(^o^)/~匈牙利算法闪亮登场
先来说一说匈牙利算法的最核心思想吧—–找增广路
(⊙o⊙)…额,什么是增广路?_?
先要说一下什么叫做交替路:
在已有匹配P的二分图中,存在路径S,v1、v2、v3、v4……∈S,v1∈P,v2∉P,v3∈P,v4∉P……,那么S就是一条交替路
所谓增广路,就是起点和终点都∉P的一条交替路
下图中,9->4->8->1->6->2就是一条增广路
增广路一定是奇数条边,因为除了起点和终点其他点都是匹配点,一定存在奇数条边(偶数条匹配边,这是显然的,奇数条未匹配边),再加上由起点和终点衍生出来的两条未匹配边,一定是奇数条边……..
仔细观察,我们会发现,增广路中未匹配路径比匹配路径要多一条,这是很显然的……………因为刚刚我们说明了,除了起点和终点其他点都是匹配点,一定存在奇数条边(偶数条匹配边,这是显然的,奇数条未匹配边),并且未匹配边的个数比匹配边的个数少一,再加上由起点和终点衍生出来的两条未匹配边,所以未匹配边的个数比匹配边的个数多一…………..
有了以上性质,我们就可以计算最大匹配了
首先说有向边:
每一次从一个点出发,寻找增广路,如果找到了增广路,证明匹配数需要+1………………然后就没有然后了
等等!!有个重要问题!!怎么找增广路呢??
依次考虑每个左部节点,为其找到一个右部节点与之匹配。
一个右部节点能与之匹配,必满足一下两个条件之一:
1、这个节点尚未与任何左部节点匹配,此时直接把两个节点进行匹配
2、从该节点匹配的左部节点出发,可以找到一个未标记的右部节点与之匹配,此时给该节点打上标记,递归进入那个左部节点,为它寻找匹配节点
代码如下:
#include<algorithm>#include<iostream>#include<cstring>#include<cstdio>using namespace std;const int maxn=500+5,maxm=10000+5;int n,k,hd[maxn*2],to[maxm],nxt[maxm],ans,vis[maxn*2],cnt,pre[maxn*2];inline int read(void){ char ch=getchar(); int f=1,x=0; while(!(ch>='0'&&ch<='9')){ if(ch=='-') f=-1; ch=getchar(); } while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar(); return f*x;}inline void add(int x,int y){ to[cnt]=y; nxt[cnt]=hd[x]; hd[x]=cnt++;}bool dfs(int u){ for(int i=hd[u];i!=-1;i=nxt[i]){ if(!vis[to[i]]){ vis[to[i]]=true; if(pre[to[i]]==-1||dfs(pre[to[i]])){ pre[to[i]]=u; return true; } } } return false;}signed main(void){ memset(hd,-1,sizeof(hd)),cnt=0; memset(pre,-1,sizeof(pre)); n=read(),k=read(); while(k--) add(read(),read()+n); for(int i=1;i<=n;i++){ memset(vis,0,sizeof(vis)); if(dfs(i)) ans++; } cout<<ans<<endl; return 0;}
接下来说无向边:
考虑每个未匹配的左部节点,为其寻找一个可以匹配的右部节点,右部节点的匹配条件相同
这里借用一下YOUSIKI童鞋的代码(自己懒得再写一遍了(⊙o⊙)…懒癌晚期……….),希望YOUSIKI童鞋不要收版权费>_<
#include<cstdio>#include<cstring>using namespace std;const int N=1005,M=20005;int n,m,hd[N],to[M],nt[M],tot,mch[N],chk[N];inline void addEdge(int x,int y){nt[tot]=hd[x],to[tot]=y,hd[x]=tot++;}inline bool dfs(int u){ for(int i=hd[u];~i;i=nt[i])if(!chk[to[i]]){ chk[to[i]]=1;if(mch[to[i]]==-1||dfs(mch[to[i]])){ mch[u]=to[i],mch[to[i]]=u;return true;} }return false;}signed main(void){ scanf("%d%d",&n,&m); memset(hd,-1,sizeof(hd)),tot=0; for(int i=1,x,y;i<=m;i++) scanf("%d%d",&x,&y),y+=n, addEdge(x,y),addEdge(y,x); int ans=0;memset(mch,-1,sizeof(mch)); for(int i=1;i<=n;i++)if(mch[i]==-1){ memset(chk,0,sizeof(chk)); if(dfs(i))ans++; }printf("%d\n",ans);}//代码好短>_<.............
by >o< neighthorn
- POJ 3041 Asteroids
- poj 3041 Asteroids
- POJ-3041 Asteroids
- Poj 3041 Asteroids
- poj 3041 Asteroids
- poj 3041 Asteroids
- POJ:3041Asteroids
- poj 3041 Asteroids
- POJ 3041 Asteroids
- POJ 3041 Asteroids
- POJ 3041 Asteroids
- POJ 3041 Asteroids
- POJ 3041 Asteroids
- poj 3041-Asteroids
- POJ 3041 Asteroids
- POJ-3041-Asteroids
- POJ 3041 Asteroids
- POJ 3041 Asteroids
- 蓝桥杯 ADV-146算法提高 计算器
- js == 与 === 的区别
- PAT甲级.1065. A+B and C (64bit) (20)
- 蓝桥杯 ADV-165算法提高 超级玛丽(动态规划、递推)
- 017——hibernate条件查询
- POJ 3041 Asteroids
- 1.CGI 简介
- 蓝桥杯 ADV-166算法提高 聪明的美食家
- 110. Balanced Binary Tree
- uva 10118 Free Candies dp(分析+状压)
- 实时流分析模式
- (精)戏说高质量代码
- 蓝桥杯 ADV-150算法提高 周期字串
- ADK - SnowMountain场景制作(三)