BZOJ1539/POI2005 Double-row

6 篇文章 0 订阅

由于数据保证有一组方案达到目标,那么相同高度的士兵个数不超过2. 每列交换的次数最多是1,多次交换是无意义的.
那么假如身高相同的两个士兵在同一行中,它们所在的列数a,b中一定有一列要进行交换,且只有一列.
那么假如身高相同的两个士兵在不同行中,它们所在的列数a,b中要么都进行交换,或者都不进行交换.
有了列与列之间的关系就可以建对以上两类情况分别建边,进行01染色,将边分为两个集合,每次选择较小集合进行操作.

#include<cstdio>
#include<cstring>
#include<iostream>
#include<vector>
#include<algorithm>
using namespace std;
const int M=5e4+5;
int a[M<<1],b[M<<1],f[M],n,mark[M],cnt[2];
struct node{
    int to,v;///v=0,相同,v=1不能相同 
};
inline void rd(int &res){
    res=0;char c;
    while(c=getchar(),c<48);
    do res=(res<<1)+(res<<3)+(c^48);
    while(c=getchar(),c>=48);
}
vector<node>e[M];
void dfs(int x){
    cnt[mark[x]]++;
    for(int i=0;i<e[x].size();i++){
        int y=e[x][i].to,v=e[x][i].v;
        if(~mark[y])continue;
        mark[y]=v^mark[x];
        dfs(y);
    }
}
int main(){
    int i,j,k,ans=0;
    memset(mark,-1,sizeof(mark));
    scanf("%d",&n);
    for(i=1;i<=n;i++){
        rd(k);
        if(a[k]){
            e[i].push_back((node){a[k],1});
            e[a[k]].push_back((node){i,1});
            f[i]=f[a[k]]=1;
        }
        a[k]=i;
    }
    for(i=1;i<=n;i++){
        rd(k);
        if(a[k]){
            e[a[k]].push_back((node){i,0});//必须相同
            e[i].push_back((node){a[k],0}); 
        }
        else if(b[k]){
            e[i].push_back((node){b[k],1});
            e[b[k]].push_back((node){i,1});
            f[i]=f[b[k]]=1;
        }
        b[k]=i;
    }
    for(i=1;i<=n;i++){
        if(f[i]&&mark[i]==-1){
            cnt[0]=0,cnt[1]=0;
            mark[i]=1;
            dfs(i);
            ans+=min(cnt[0],cnt[1]);
        }
    }
    printf("%d\n",ans);
    return 0;
}
  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值