您的位置:首页 > 其它

POJ 1486(二分图匹配)二分图的完全匹配的必须边

2012-08-29 22:05 381 查看
题意:给你n个幻灯片,每个幻灯片有个数字编号1~n,现在给每个幻灯片用A~Z进行编号,那么问有多少个幻灯片的数字和字母是唯一对应的

二分图的完全匹配的必须边,裸的。

这道题目可以用

/article/5211296.html

方法来解。。但是我的第一反应就是删边。于是乎,用删边的方法做的

先做一遍匹配,匈牙利。然后对于匹配中的每条边都删除一遍,如果不能达到完全匹配,则这条边是必须边。

大致思想就是这样了

代码里几个我犯错的地方写了注释

View Code

#include <cstdio>
#include <cstdlib>
#include <cstring>
#define N 40
#define M 1600
using namespace std;
int n,x1
,x2
,y1
,y2
,x,y,head
,next[M],to[M],bh

,ban,cnt,linky
,first_ans,cas;
bool vis
;
void add(int u,int v)
{
to[cnt]=v; next[cnt]=head[u]; head[u]=cnt++;
}
void read()
{
memset(head,-1,sizeof head);cnt=0;
for(int i=1;i<=n;i++) scanf("%d%d%d%d",&x1[i],&x2[i],&y1[i],&y2[i]);
for(int i=1;i<=n;i++)
{
scanf("%d%d",&x,&y);
for(int j=1;j<=n;j++)
if(x>x1[j]&&x<x2[j]&&y>y1[j]&&y<y2[j])
{
bh[i][j]=cnt;//两点连线的编号
add(i,j);
}
}
}
bool dfs(int u)
{
for(int i=head[u];~i;i=next[i])
if(!vis[to[i]]&&ban!=i)
{
vis[to[i]]=true;
if(linky[to[i]]==-1||dfs(linky[to[i]]))
{
linky[to[i]]=u;
return true;
}
}
return false;
}
void first_match()
{
memset(linky,-1,sizeof linky);
for(int i=1;i<=n;i++)
{
memset(vis,0,sizeof vis);
if(dfs(i)) first_ans++;
}
}
void go()
{
ban=-1;
first_match();
bool bj=false;
printf("Heap %d\n",cas);
for(int i=1,tmp;i<=n;i++)
{
tmp=linky[i];
ban=bh[tmp][i];//ban是删的边,注意tmp是左边的点,i是右边的点
linky[i]=-1;
memset(vis,0,sizeof vis);
if(!dfs(tmp))
{
bj=true,printf("(%c,%d) ",'A'+i-1,tmp);
linky[i]=tmp;//必须放在括号内,因为如果dfs返回true的话说明有新的匹配,linky不能更新
}
}
if(bj) printf("\n\n");
else printf("none\n\n");
}
int main()
{
while(scanf("%d",&n),n)
{
cas++;
read();
go();
}
return 0;
}


话说,我这个蒟蒻POJ终于到了300题了。。

还是太弱,XLk神牛每天40题呢。。

OTZZZZZZZZZZZZZZZZZZZZZZZZZZZZZ
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: