zoukankan      html  css  js  c++  java
  • codeforces #309 div1 D

    求最小值最大显然是要二分

    二分之后转换成了判定性问题

    我们考虑哪些点一定不能选

    显然是将所有可选点选中之后依然不满足条件的点不能选

    那么我们不妨维护一个堆,每次取出堆顶看看是否满足条件

    不满足条件就pop掉,并进行松弛

    最后判定堆是否为空即可

    另外,其实这道题思考到这里我们会发现二分并没有什么卵用,可以去掉二分省掉一个log

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<algorithm>
    #include<cstdlib>
    #include<queue>
    using namespace std;
    
    const int maxn=100010;
    int n,m,k,x,u,v,tot;
    bool vis[maxn];
    bool check[maxn];
    int deg[maxn];
    int sum[maxn];
    int ans[maxn];
    int h[maxn],cnt=0;
    struct edge{
    	int to,next;
    }G[maxn<<1];
    
    struct pos{
    	double k;//����
    	int now;//��ǰ��
    	pos(double k=0,int now=0):k(k),now(now){}
    	bool operator <(const pos &A)const{
    		return k>A.k;
    	}
    };
    
    priority_queue<pos>Q;
    
    void add(int x,int y){++cnt;G[cnt].to=y;G[cnt].next=h[x];h[x]=cnt;}
    
    bool Get_check(double k){
    	memset(check,0,sizeof(check));
    	memset(deg,0,sizeof(deg));
    	while(!Q.empty())Q.pop();
    	for(int u=1;u<=n;++u){
    		if(vis[u])continue;
    		for(int i=h[u];i;i=G[i].next){
    			int v=G[i].to;
    			if(vis[v])continue;
    			deg[v]++;
    		}
    	}
    	for(int i=1;i<=n;++i){
    		if(vis[i])continue;
    		Q.push(pos((double)(deg[i])/sum[i],i));
    	}
    	while(!Q.empty()){
    		while(!Q.empty()&&check[Q.top().now])Q.pop();
    		if(Q.empty())break;
    		pos tmp=Q.top();
    		if(tmp.k>=k)break;
    		int u=tmp.now;check[u]=true;
    		for(int i=h[u];i;i=G[i].next){
    			int v=G[i].to;
    			if(check[v]||vis[v])continue;
    			deg[v]--;
    			Q.push(pos((double)(deg[v])/sum[v],v));
    		}
    	}
    	if(Q.empty())return false;
    	return true;
    }
    
    int main(){
    	scanf("%d%d%d",&n,&m,&k);
    	for(int i=1;i<=k;++i){
    		scanf("%d",&x);
    		vis[x]=true;
    	}
    	for(int i=1;i<=m;++i){
    		scanf("%d%d",&u,&v);
    		add(u,v);add(v,u);
    		sum[u]++;sum[v]++;
    	}
    	double L=0,R=1;
    	for(int i=1;i<=50;++i){
    		double mid=(L+R)/2;
    		if(Get_check(mid))L=mid;
    		else R=mid;
    	}
    	Get_check(L);tot=0;
    	for(int i=1;i<=n;++i){
    		if(check[i]||vis[i])continue;
    		ans[++tot]=i;
    	}
    	printf("%d
    ",tot);
    	for(int i=1;i<=tot;++i)printf("%d ",ans[i]);
    	return 0;
    }
    

      

  • 相关阅读:
    VS一个奇怪的发布问题
    VS删除空白行
    IDEA Rider 准备试用一段时间(1)
    IDEA Rider使用64位IISExpress(3)
    IDEA rider 管道模式 经典模式(2)
    VSCode批量替换使用注意问题
    IScroll Unable to preventDefault inside passive event listener due to target being treated as passive
    数据库索引也不是多多益善
    css设置手型光标
    javascript参数化拼接字符串两种方法
  • 原文地址:https://www.cnblogs.com/joyouth/p/5362005.html
Copyright © 2011-2022 走看看