[POI2005]DWU-Double-row

题目

题目描述
2n2n soldiers are standing in a double-row. They have to be rearranged, so that there are no equally tall soldiers in each row - then we shall say, that the soldiers are set up properly.

A single operation consists in swapping two soldiers who occupy the same position (but in different rows). Your task is to determine the minimum number of swaps necessary to set the soldiers up properly.

Example:

There is a double-row of 1818 soldiers in the figure. Arrows indicate the swaps that rearrange the soldiers in a proper way.

TaskWrite a programme that:

reads from the standard input the number and heights of soldiers, as they stand initially,determines the minimum number of swaps (of soldiers standing on the same position in different rows) necessary to set up soldiers properly,writes the result to the standard output.

一句话题意By Scarlet:2n2n个数站成两排(每个数在2n2n个数中最多出现两遍),一次操作可以交换任意一列中两个数,求使每行数不重复的最少操作数。

输入格式
In the first line of the input there is one integer nn, 1\le n\le 50\ 0001≤n≤50 000. In each of the two rows there are nn soldiers standing. In each of the following two lines there are nn positive integers separated by single spaces. In the second line there are numbers x_1,x_2,\cdots,x_nx
1

,x
2

,⋯,x
n

, 1\le x_i\le 100\ 0001≤x
i

≤100 000; x_ix
i

denotes the height of the ii’th soldier in the first line. In the third line there are numbers y_1,y_2,\cdots,y_ny
1

,y
2

,⋯,y
n

, 1\le y_i\le 100\ 0001≤y
i

≤100 000; y_iy
i

denotes the height of the ii’th soldier in the second line.

It is guaranteed that in the instances from the test data it is possible to set up soldiers properly.

输出格式
In the first and only line of the standard output one integer should be written - the minimum number of swaps necessary to set up soldiers properly.

题意翻译
题目描述

有2n个士兵站成两排,他们需要被重新排列,以保证每一排里没有同样高的士兵——这样我们就说,士兵们被合理地安排了位置。 每次操作可以交换两个在同一位置(但不在同一排)的士兵。你的任务是用最少的操作来确保士兵们被合理地安排了位置。 例如: 有18个士兵站成两排,箭头标明了重新安排士兵位置的正确方式(图飞了?)。 写一个这样的程序: 读入n与士兵的身高,以及他们最初所站的位置,确保以最小的交换(站在同一位置的不同排的士兵)的次数来合理地安排士兵的位置,输出操作数。

输入格式

第一行为一个整数n(1<=n<=50000),接下来的两行每行有n个数表示每行站着的n个士兵的身高(1<=士兵的身高<=100000)。 数据保证你能够合理地安排士兵的位置(即每个数在2n个数中最多出现两次)。

输出格式

只有一行,输出最小操作数。 翻译贡献者UID:57699

输入输出样例
输入 #1复制
9
2 5 5 2 7 4 7 3 9
1 6 8 4 6 3 9 1 8
输出 #1复制
3

思路

脑力锻炼题
如果两个相同的数在不在同一行,给两个数所在的列的编号连一条边权为0的边
如果两个相同的数在同一行,给两个数所在的列的编号连一条边权为1的边
给每个联通块的点黑白染色(1边连接的点颜色相反,0边连接的点颜色相同),答案就是sigma(每个联通块的min(black,white))

代码

#include<bits/stdc++.h>
using namespace std;
int pos[100010][2];
int n,tmp0;
struct E
{
    int v,w;
    E *next;
}*h[50010],pool[100010];
int top;
void add(int u,int v,int w)
{
    E *tmp=&pool[top++];tmp->v=v;tmp->w=w;tmp->next=h[u];h[u]=tmp;
    E *pmt=&pool[top++];pmt->v=u;pmt->w=w;pmt->next=h[v];h[v]=pmt;
}
int vis[50010],col[50010],cntc[2],cnt,ans;
void dfs(int u)
{
    vis[u]=1;
    cntc[col[u]]++;
    for(E *tmp=h[u];tmp;tmp=tmp->next)
    {
        if(!vis[tmp->v])
        {
            col[tmp->v]=col[u]^tmp->w;
            dfs(tmp->v);
        }
    }
}
int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&tmp0);
        if(pos[tmp0][0])pos[tmp0][1]=i;
        else pos[tmp0][0]=i;
    }
    for(int i=1;i<=n;i++)
    {
        scanf("%d",&tmp0);
        if(pos[tmp0][0])pos[tmp0][1]=-i;
        else pos[tmp0][0]=-i;
    }
    for(int i=1;i<=100000;i++)
    {
        if(pos[i][0]&&pos[i][1])
        {
            add(abs(pos[i][0]),abs(pos[i][1]),!((pos[i][0]>0)^(pos[i][1]>0)));
        }
    }
    for(int i=1;i<=n;i++)
    {
        if(!vis[i])
        {
            cntc[0]=cntc[1]=0;
            dfs(i);
            ans+=min(cntc[0],cntc[1]);
        }
    }
    printf("%d\n",ans);
    return 0;
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值