您的位置:首页 > 其它

bzoj 1539: [POI2005]Dwu-Double-row

2017-03-12 19:28 176 查看
  假设一列交换表示为1,不换表示为0.

  身高相同的两个人相当于给其中两列了一个限制条件,要么是两个必须相等,要么一个为零一个为一。

  有了关系后我们就可以把每列当成一个点建边,边权为0表示必须相同,1为必须不同,这样每个联通块会被分为两个确定的集合,把$size$小的交换就行了。

  

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#define N 100005
using namespace std;
int n;
int cnt[2];
int v
,vis
;
int be
,pos
;
int head
,ver
,nxt
,tot,quan
;
void add(int a,int b,int c)
{
tot++;nxt[tot]=head[a];head[a]=tot;quan[tot]=c;ver[tot]=b;return ;
}
void dfs(int x,int b)
{
vis[x]=1;cnt[b]++;
for(int i=head[x];i;i=nxt[i])
{
if(!vis[ver[i]])
{
dfs(ver[i],(b+quan[i])&1);
}
}
return ;
}
int main()
{
scanf("%d",&n);
for(int i=1;i<=n;i++)
{
int tmp;
scanf("%d",&tmp);
if(be[tmp])
{
add(be[tmp],i,1);
add(i,be[tmp],1);
}
else be[tmp]=i,pos[tmp]=1;
}
for(int i=1;i<=n;i++)
{
int tmp;
scanf("%d",&tmp);
if(be[tmp])
{
if(pos[tmp]==1)
{
add(be[tmp],i,0);
add(i,be[tmp],0);
}
else
{
add(be[tmp],i,1);
add(i,be[tmp],1);
}
}
else be[tmp]=i,pos[tmp]=2;
}
int ans=0;
for(int i=1;i<=n;i++)
{
if(!vis[i])
{
cnt[0]=cnt[1]=0;
dfs(i,0);
ans+=min(cnt[0],cnt[1]);
}
}
printf("%d\n",ans);
return 0;
}


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