bzoj 1539: [POI2005]Dwu-Double-row

  假设一列交换表示为1,不换表示为0.

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

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

  

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cstring>
 4 #include<algorithm>
 5 #define N 100005
 6 using namespace std;
 7 int n;
 8 int cnt[2];
 9 int v[N],vis[N];
10 int be[N],pos[N];
11 int head[N],ver[N],nxt[N],tot,quan[N];
12 void add(int a,int b,int c)
13 {
14     tot++;nxt[tot]=head[a];head[a]=tot;quan[tot]=c;ver[tot]=b;return ;
15 }
16 void dfs(int x,int b)
17 {
18     vis[x]=1;cnt[b]++;
19     for(int i=head[x];i;i=nxt[i])
20     {
21         if(!vis[ver[i]])
22         {
23             dfs(ver[i],(b+quan[i])&1);
24         }
25     }
26     return ;
27 }
28 int main()
29 {
30     scanf("%d",&n);
31     for(int i=1;i<=n;i++)
32     {    
33         int tmp;
34         scanf("%d",&tmp);
35         if(be[tmp])
36         {
37             add(be[tmp],i,1);
38             add(i,be[tmp],1);
39         }
40         else be[tmp]=i,pos[tmp]=1;
41     }
42     for(int i=1;i<=n;i++)
43     {    
44         int tmp;
45         scanf("%d",&tmp);
46         if(be[tmp])
47         {
48             if(pos[tmp]==1)
49             {
50                 add(be[tmp],i,0);
51                 add(i,be[tmp],0);
52             }
53             else
54             {
55                 add(be[tmp],i,1);
56                 add(i,be[tmp],1);
57             }
58         }
59         else be[tmp]=i,pos[tmp]=2;
60     }
61     int ans=0;
62     for(int i=1;i<=n;i++)
63     {
64         if(!vis[i])
65         {
66             cnt[0]=cnt[1]=0;
67             dfs(i,0);
68             ans+=min(cnt[0],cnt[1]);
69         }
70     }
71     printf("%d\n",ans);
72     return 0;
73 }

 

  

posted @ 2017-03-12 19:28  SD_le  阅读(274)  评论(0编辑  收藏  举报
重置按钮