题目大意
有n只袜子,有至多k种颜色,给你m天的安排,要你穿两只,要保证两只袜子同色。每只袜子可以至多染一次色。
问最小的染色次数。
思路:
讲真的一开始没想到用搜索,事实上题目可以这么理解,我的第i只袜子可能与之前之后都有联系,那么袜子最后肯定会分成几个堆,堆之间没关系。给个数据
10 3 2
2 1 1 2 1 1 2 1 2 2
4 10
9 3
5 7
三天间就没什么联系。那么每次搜索一下,搜索到的袜子标记一下。
需要更改的袜子数就等于所有堆各自的袜子总数减去同一颜色的最大数!
好好消化一下就会发现很巧妙!
上代码:
#include<bits/stdc++.h>
#define input freopen("input.txt","r",stdin)
using namespace std;
vector<int>s[200002];
int n,m,k;
int tot,maxx;
int value[200002],v[200002]; //v是标记,value是袜子的颜色值
map<int,int>p; //记录每堆最大的颜色数
void dfs(int pos)
{
if(v[pos]) return ; //如果碰到标记的结束
v[pos]=1;
tot++; //总数增加
maxx=max(maxx,++p[value[pos]]); //注意里面有个先++啊!
for(int i=0;i<s[pos].size();i++) //跑他的 连接点搜索(堆内的搜索)
dfs(s[pos][i]);
}
int main()
{
input;
int i,j;
long long ans;
while(cin>>n>>m>>k)
{
memset(v,0,sizeof(v));
for(i=1;i<=n;i++) s[i].clear();
for(i=1;i<=n;i++) cin>>value[i];
for(i=1;i<=m;i++)
{
int l,r;
cin>>l>>r;
s[l].push_back(r);//双向的图
s[r].push_back(l);
}
for(ans=0,i=1;i<=n;i++)
{
tot=maxx=0;//这两步! 一定要初始化
p.clear();
dfs(i);
ans+=(tot-maxx);
}
cout<<ans<<endl;
}
return 0;
}