zoukankan      html  css  js  c++  java
  • bzoj 1312: Hard Life 01分数规划+网络流

    题目:

    Description
    在一家公司中,人事部经理与业务部经理不和。一次,总经理要求人事部从公司的职员中挑选出一些来帮助业务部经理完成一项任务。人事部经理发现,在公司的所有职员中,有一些人相处得很不好。如果把他们同时放在一个工作小组中,他们将会给主管带来不小的麻烦。人事部经理还知道,在一个工作小组中,主管人员的麻烦程度可以认为是(带来麻烦的人的对数/总人数) 。于是,人事部经理决定选取这样的一些人,使得业务部经理的麻烦度最大。你的任务是帮助人事部经理达到他的目的。 在这样的一个公司中,保证公司的人数小于100 人,带来麻烦的员工不会多于1000 对。
    Input
    第一行给出N,M代表共有N个人,M对人之间有怨念 下面M行,每行两个数,代表这两个人有怨念
    Output
    输出最多能找出多少个人,人数>=1

    题解:

    我不想写这道题的题解







    Sky_miner是我的号hzoi_admin是我提交次数不够了借用的号.
    求不D

    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #include <queue>
    #include <cmath>
    using namespace std;
    typedef int ll;
    inline void read(int &x){
    	x=0;char ch;bool flag = false;
    	while(ch=getchar(),ch<'!');if(ch == '-') ch=getchar(),flag = true;
    	while(x=10*x+ch-'0',ch=getchar(),ch>'!');if(flag) x=-x;
    }
    const int maxn = 80048;
    const int maxm = 100005;
    const int maxnode = (maxn+maxm)<<1;
    struct Edge{
    	int to,next;
    	long double cap;
    }G[maxnode];
    int head[maxnode],cnt=1;
    void add(int u,int v,long double c){
    	G[++cnt].to = v;
    	G[cnt].next = head[u];
    	head[u] = cnt;
    	G[cnt].cap = c;
    }
    inline void insert(int u,int v,long double c){
    	add(u,v,c);add(v,u,0);
    }
    inline void clear(){
    	memset(head,-1,sizeof head);
    	cnt = 1;
    }
    #define v G[i].to
    int dis[maxnode];
    int S,T;
    inline bool bfs(){
    	memset(dis,-1,sizeof dis);
    	queue<int>q;q.push(S);
    	dis[S] = 0;
    	while(!q.empty()){
    		int u = q.front();q.pop();
    		for(int i = head[u];i != -1;i=G[i].next){
    			if(dis[v] == -1 && G[i].cap > 1e-8){
    				dis[v] = dis[u] + 1;
    				q.push(v);
    			}
    		}
    	}return dis[T] != -1;
    }
    long double dfs(int u,long double f){
    	if(u == T || fabs(f) < 1e-8) return f;
    	long double ret = 0;
    	for(int i = head[u];i != -1;i=G[i].next){
    		if(dis[v] == dis[u] + 1 && G[i].cap > 1e-8 ){
    			long double x = dfs(v,min(G[i].cap,f));
    			ret += x;f -= x;
    			G[i].cap -= x;
    			G[i^1].cap += x;
    			if(fabs(f) < 1e-8) break;
    		}
    	}return ret;
    }
    #undef v
    inline long double dinic(){
    	long double ret = 0;
    	while(bfs()) ret += dfs(S,1e9);
    	return ret;
    }
    struct Node{
    	int u,v;
    }e[maxm];
    int n,m;
    bool check(double ans){
    	memset(head,-1,sizeof(head));cnt=1;
    	double sum=m;S=0;T=n+m+1;
    	for(int i=1;i<=n;++i){
    		insert(S,i,ans);
    	}
    	for(int i=1;i<=m;++i){
    		insert(n+i,T,1);
    		insert(e[i].u,n+i,1e9);
    		insert(e[i].v,n+i,1e9);
    	}
    	return sum>dinic();
    }
    int dfn[maxn];
    int ans;
    void DFS(int x){
    	if(1<=x&&x<=n)ans--;
    	dfn[x]=1;
    	for(int pt=head[x];pt!=-1;pt=G[pt].next){
    		if(G[pt].cap>1e-3&&!dfn[G[pt].to])DFS(G[pt].to);
    	}
    }
    int main(){
    	read(n);read(m);
    	if(m == 0) return puts("1");
    	for(int i=1;i<=m;++i){
    		read(e[i].u);read(e[i].v);
    	}
    	long double l = .0,r = 1e4;
    	while(l + 1e-5 < r){
    		long double mid = (l+r)/2.0;
    		if(check(mid)) l = mid;
    		else r = mid;
    	}ans = n;
    	DFS(S);
    	printf("%d
    ",max(ans,1));
    	getchar();getchar();
    	return 0;
    }
    
  • 相关阅读:
    电脑端与iPad 端如何共享ChemDraw结构
    用几何画板绘制带根号坐标点的方法
    几何画板使用方法
    如何在ChemDraw中缩短双键长度
    如何在ChemDraw中打出符号π
    怎么用几何画板制作图形平移和旋转
    怎么用几何画板制作三维波纹
    如何在ChemDraw中输入℃温度符号
    怎么用ChemDraw加反应条件
    MathType中输入不了汉字如何处理
  • 原文地址:https://www.cnblogs.com/Skyminer/p/6550838.html
Copyright © 2011-2022 走看看