• P2323 [HNOI2006]


    Miku

    一眼就看出来是个二分答案

    二分最大边的权值

    然后显然这种题是不需要考虑花了多少钱的,那么对于每一个mid

    就先把所有范围内1级边全键了,然后再把剩下的二级边全键了,看一下能不能跑出来一个生成树

    就行了

    //二分解决最大的最小 
    #include<iostream>
    #include<algorithm>
    #include<cstdio>
    using namespace std;
    int l,r;
    int n,k,m;
    int a,b;
    int use1[80001];
    int use2[80001];
    struct e{
    	int f;
    	int to;
    	int ne;
    	int co;
    	int id;
    }e1[80001],e2[80001];
    int head1[80001],head2[80001];
    int fa[80001];
    int p1,p2;
    int c1,c2;
    int mid;
    int read(){
    	int v=0;
    	char c;
    	int f=1;
    	c=getchar();
    	while(c<'0'||c>'9'){
    		if(c=='-'){
    			f=-1;
    		}
    		c=getchar();
    	}
    	while('0'<=c&&c<='9'){
    		v=v*10+c-'0';
    		c=getchar();
    	}
    	return v*f;
    }
    void add1(int f,int to,int v,int id){
    	p1++;
    	e1[p1].co=v;
    	e1[p1].f=f;
    	e1[p1].id=id;
    	e1[p1].to=to;
    	e1[p1].ne=head1[f];
    	head1[f]=p1;
    	return ;
    }
    int find(int x){
    	return x==fa[x] ? x:fa[x]=find(fa[x]);
    }
    bool com(int x,int y){
    	if(find(x)!=find(y)){
    		fa[find(x)]=find(y);
    		return 1;
    	}
    	return 0;
    }
    void add2(int f,int to,int v,int id){
    	p2++;
    	e2[p2].co=v;
    	e2[p2].id=id;
    	e2[p2].f=f;
    	e2[p2].to=to;
    	e2[p2].ne=head2[f];
    	head2[f]=p2;
    	return ;
    }
    bool cmp(e x,e y){
    	return x.co<y.co;
    }
    bool check(int li){
    	int cnt=0;
    	for(int i=1;i<=n;++i)
    	fa[i]=i;
    	for(int i=1;i<m;++i){
    		if(e1[i].co>li)
    		break;
    		if(com(e1[i].to,e1[i].f)){
    		cnt++; 
    //		e1[i].id=l;
    		use1[e1[i].id]=l;
    		} 
    		if(cnt==n-1)
    		break;
    	} 
    	if(cnt<k)
    	return 0;
    	for(int i=1;i<m;++i){
    		if(e2[i].co>li)
    		break;
    		if(com(e2[i].to,e2[i].f)){
    		cnt++; 
    		use2[e2[i].id]=l;
    //		e2[i].id=l;
    		} 
    		if(cnt==n-1)
    		return 1;
    	}
    	return 0;
    }
    int main(){
    	n=read();
    	k=read();
    	m=read();
    	for(int i=1;i<m;++i){
    		a=read();b=read();
    		c1=read();c2=read();
    		add1(a,b,c1,i*2-1);
    		add2(a,b,c2,i*2);
    	}
    	sort(e1+1,e1+m+1,cmp);
    	sort(e2+1,e2+m+1,cmp);
    	l=e1[k].co;
    	r=max(e1[m].co,e2[m].co);
    	while(l<=r){
    		mid=l+(r-l)/2; 
    		if(check(mid)){
    			r=mid-1;
    		}else{
    			l=mid+1;
    		}
    	}
    	check(l);
    	cout<<l<<endl;
    	for (int i=1;i<m;++i){
    		if(use1[i*2-1]==l){
    			printf("%d 1
    ",i);
    		}else{
    			if(use2[i*2]==l){
    			printf("%d 2
    ",i);
    		}
    		}
    	}
    	return 0;
    } 
    
  • 相关阅读:
    十二周作业
    十一周作业
    第十周作业
    第九周作业
    第八周作业
    第七周作业
    2019年第六周作业
    第五周作业总结
    介绍自己
    第一学期总结
  • 原文地址:https://www.cnblogs.com/For-Miku/p/13473633.html
Copyright © 2020-2023  润新知