P2323 [HNOI2006]公路修建问题 (二分)
二分最小值,能选第一个尽量选,之后选第二个看看能否满足答案
#include<bits/stdc++.h> using namespace std; typedef long long ll; const int N=3e5+10; const int mod=1e7+7; int n,m,k; struct node{ int a,b; ll c1,c2; }s[N]; int p[N]; int ans[N]; int st[N]; int find(int x){ if(p[x]!=x){ p[x]=find(p[x]); } return p[x]; } bool check(int x){ int i; for(i=1;i<=n;i++) p[i]=i; memset(st,0,sizeof st); int cnt=0; for(i=1;i<=m;i++){ int pa=find(s[i].a); int pb=find(s[i].b); if(s[i].c1<=x){ if(pa!=pb){ cnt++; p[pa]=pb; st[i]=1; } } } int d=0; for(i=1;i<=m;i++){ int pa=find(s[i].a); int pb=find(s[i].b); if(s[i].c2<=x){ if(pa!=pb){ d++; p[pa]=pb; st[i]=2; } } } if(cnt>=k&&(cnt+d)==n-1){ for(i=1;i<=m;i++){ ans[i]=st[i]; } return true; } return false; } int main(){ ios::sync_with_stdio(false); cin>>n>>k>>m; int i; m--; for(i=1;i<=m;i++){ int a,b,c,d; cin>>a>>b>>c>>d; s[i]={a,b,c,d}; } int l=1,r=30000; while(l<r){ int mid=l+r>>1; if(check(mid)) r=mid; else l=mid+1; } cout<<l<<endl; for(i=1;i<=m;i++){ if(ans[i]) cout<<i<<" "<<ans[i]<<endl; } return 0; }
没有人不辛苦,只有人不喊疼