题目
题解思路
这题思路还是比较明显的,将颜色需要相同的气球全部并查起来,在搜索集合中颜色最多的颜色,将其他的也染成这个。这样贪心就能保证使用的染色最少。
时间复杂度为On,看起来这样复杂很高,实际上每个点之会属于一个集合,所以每个点只走了一次。
两端代码的不同让我找了好久的bug。
if ( a[i] == i )
{
vector <int> pk ;
vis[i] = cnt ;
pk.push_back(b[i]) ;
cnt ++ ;
head.push_back(pk) ;
}
if ( find(i) == i )
{
vector <int> pk ;
vis[i] = cnt ;
pk.push_back(b[i]) ;
cnt ++ ;
head.push_back(pk) ;
}
当验证父节点关系的时候必须用find函数,不能直接判断。
因为
这种情况下2号节点根本来不及路径压缩,所以当验证父节点的时候必须用find函数来验证
之前想过这种情况,因为在uio()加个find(y)就行,这里只想了2连3,却没想到1连3这种情况。
AC代码
#include <bits/stdc++.h>
//#include <unordered_map>
//priority_queue
#define PII pair<int,int>
#define ll long long
using namespace std;
const int INF = 0x3f3f3f3f;
const int N = 200100 ;
int n , m , k ;
int a[N] ;
int b[N] ;
vector <vector <int> >head ;
int vis[N] ;
int find(int x )
{
if ( x != a[x] )
return a[x] = find(a[x]) ;
return a[x] ;
}
void uio(int x , int y )
{
int fx = find(x) ;
int fy = find(y) ;
if (fx != fy )
{
a[fy] = fx ;
find(y) ;
}
}
int main()
{
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
cin >> n >> m >> k ;
for (int i = 1 ; i <= n ; i++ )
a[i] = i ;
for (int i = 1 ; i <= n ; i++ )
cin >> b[i] ;
for (int i = 1 ; i <= m ; i++ )
{
int t1 , t2 ;
cin >> t1 >> t2 ;
uio( t1 , t2 ) ;
}
int cnt = 0 ;
for (int i = 1 ; i <= n ; i++ )
{
if ( find(i) == i )
{
vector <int> pk ;
vis[i] = cnt ;
pk.push_back(b[i]) ;
cnt ++ ;
head.push_back(pk) ;
}
}
for (int i = 1 ; i <= n ; i++ )
{
if (find(i) != i )
{
head[vis[a[i]]].push_back(b[i]) ;
}
}
int ans = 0 ;
/*
for (int i = 0 ; i < head.size() ; i++ )
{
for (int j = 0 ; j < head[i].size() ; j++ )
cout << head[i][j] << " " ;
cout << "\n" ;
}*/
for (int i = 0 ; i < head.size() ; i++ )
{
int ma = 0 ;
unordered_map <int ,int > mp ;
for (int j = 0 ; j < head[i].size() ; j++ )
{
mp[head[i][j]]++ ;
}
for (int j = 0 ; j < head[i].size() ; j++ )
{
ma = max(ma , mp[head[i][j]] );
}
if (head[i].size())
{
int sz = head[i].size() ;
ans += sz - ma ;
}
}
cout << ans << "\n" ;
return 0 ;
}