题解:P14415 [JOISC 2015] 遗产继承 / Inheritance
闲话
什么日本神题
被大手子拉过来刷题了。
正文
看了一眼,简化一下题意。
形式化题面
给定 0。
暴力
直接跑
正解
根据大手子の情报根据直觉,删边的顺序存在单调性。
具体而言,假如一条边在第
由此我们考虑维护
单次二分时间复杂度为
代码
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define V vector
#define FOR(i,a,b) for(int i=(int)(a);i<=(int)(b);i++)
#define pb push_back
const int INF=1e9+10;
struct node{
int chos,u,v,w,id;
friend bool operator <(const node &a,const node &b){
if(a.chos^b.chos) return a.chos<b.chos;
if(a.w^b.w) return a.w>b.w;
if(a.id^b.id) return a.id<b.id;
if(a.u^b.u) return a.u<b.u;
return a.v<b.v;
}
};
struct DSU{
V<int>fa;
DSU(int _n):fa(_n+1){iota(fa.begin(),fa.end(),0);}
int fin(int x){
while(x^fa[x])x=fa[x]=fa[fa[x]];
return x;
}
bool is_(int u,int v){
return fin(u)==fin(v);
}
void merge(int u,int v){
if(is_(u,v)) return;
u=fin(u),v=fin(v);
fa[u]=v;
}
};
signed main(){
ios::sync_with_stdio(false);cin.tie(0);cout.tie(0);
int n,m,k;cin>>n>>m>>k;
V<DSU> dsu(k+1,DSU(n));
V<node>e(m+1);
FOR(i,1,m){
cin>>e[i].u>>e[i].v>>e[i].w;e[i].chos=0;e[i].id=i;
}
V<int>ans(m+1,0);
sort(e.begin()+1,e.end());
auto check=[&](int edge,int x){
return dsu[x].is_(e[edge].u,e[edge].v);
};
FOR(i,1,m){
int l=1,r=k,res=0;
while(l<=r){
int mid=(l+r)>>1;
if(check(i,mid)){
l=mid+1;
}else{
res=mid;
r=mid-1;
}
}
if(res){
ans[e[i].id]=res;
dsu[res].merge(e[i].u,e[i].v);
}
}
FOR(i,1,m) cout<<ans[i]<<"\n";
return 0;
}