JOISC 2019 合并
Posted iefnah06
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了JOISC 2019 合并相关的知识,希望对你有一定的参考价值。
URL
简要题意
懒得写了
解法
考虑同色的两个点,它们路径上的每条边都是不能作为分割点的,不妨把路径上的点全部缩起来。这样之后所有点都是不同颜色的。
合并颜色的操作依旧是缩点,答案是(叶子个数+1)/2
实现
#include <bits/stdc++.h>
using namespace std;
#define rng(i,a,b) for(int i=int(a);i<int(b);i++)
#define rep(i,b) rng(i,0,b)
#define gnr(i,a,b) for(int i=int(b)-1;i>=int(a);i--)
#define per(i,b) gnr(i,0,b)
#define pb push_back
#define eb emplace_back
#define bg begin()
#define ed end()
#define all(x) (x).bg,(x).ed
#define si(x) int((x).size())
#define mp make_pair
#define a first
#define b second
#ifdef LOCAL
#define dmp(x) cerr<<__LINE__<<" "<<#x<<" "<<x<<endl
#else
#define dmp(x) void(0)
#endif
template<class t,class u> void chmax(t&a,u b){if(a<b)a=b;}
template<class t,class u> void chmin(t&a,u b){if(b<a)a=b;}
template<class t> using vc=vector<t>;
template<class t> using vvc=vc<vc<t>>;
using ll=long long;
using uint=unsigned int;
using pi=pair<int,int>;
using vi=vc<int>;
int topbit(signed t){
return t==0?-1:31-__builtin_clz(t);
}
int topbit(ll t){
return t==0?-1:63-__builtin_clzll(t);
}
struct unionfind{
vc<int> p;
unionfind(int n):p(n,-1){}
int find(int a){
return p[a]<0?a:(p[a]=find(p[a]));
}
void mg(int a,int b){
p[find(a)]=find(b);
}
};
const int nmax=5.1e5;
vi g[nmax];
int par[nmax];
int dep[nmax];
vi state[nmax];
int deg[nmax];
void dfs(int v,int p){
par[v]=p;
for(int to:g[v])if(to!=p){
dep[to]=dep[v]+1;
dfs(to,v);
}
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
int n,k;cin>>n>>k;
rep(i,n-1){
int a,b;cin>>a>>b;a--,b--;
g[a].pb(b);
g[b].pb(a);
}
par[0]=-1;
dep[0]=0;
dfs(0,-1);
rep(i,n){
int s;cin>>s;s--;
state[s].pb(i);
}
unionfind uf(n);
auto mg=[&](int a,int b)->void{
a=uf.find(a);
b=uf.find(b);
while(a!=b){
if(dep[a]<dep[b])swap(a,b);
uf.mg(a,par[a]);
a=uf.find(par[a]);
}
};
rep(i,k){
assert(si(state[i]));
rng(j,1,si(state[i]))
mg(state[i][0],state[i][j]);
}
rep(i,n)
for(int j:g[i])if(dep[i]<dep[j]&&uf.find(i)!=uf.find(j)){
deg[uf.find(i)]++;
deg[uf.find(j)]++;
}
int cnt=0;
rep(i,n)if(uf.find(i)==i&°[i]==1)cnt++;
int ans=(cnt+1)/2;
cout<<ans<<'
';
}
以上是关于JOISC 2019 合并的主要内容,如果未能解决你的问题,请参考以下文章