zoukankan      html  css  js  c++  java
  • UVA1389 Hard Life (01分数规划+最大流)

    UVA1389 Hard Life (01分数规划+最大流)

    Luogu

    题目描述略

    题解时间

    $ (frac{Sigma EdgeCount}{Sigma PointCount})_{max} $

    是什么已经不用说了⑧

    经典的01分数规划

    上来先二分答案$ ans $

    之后考虑判断

    根据选边与选点的关系

    考虑建出这样一个图:

    建立源点 $ S $ 与汇点 $ P $

    对于原图中的每条边看做一个点,从 $ S $ 向这个点建流量为 $ 1 $ 的边

    对于原图中的每个点向 $ T $ 建流量为 $ ans $ 的边

    对于原图中的每条边所代表的点,向这条边连接的两个点建流量为 $ 1 $ 的边

    跑最大流, $ maxflow leq m $ 即可

    原理?

    我们回顾一下柿子

    $ frac{Sigma EdgeCount}{Sigma PointCount} leq ans $

    转换一下就是

    $ Sigma EdgeCount-Sigma PointCount*ans leq 0 $

    好像已经很明显了⑧

    那就先这样吧(溜走)

    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<queue>
    using namespace std;
    namespace LarjaIX
    {
    const int N=2011;
    const int inf=0x3f3f3f3f;
    const double eps=1e-8;
    const double dinf=1e8;
    struct sumireko{int to,ne;double w;}e[N<<2];
    int he[N],ecnt=1;
    void addline(int f,int t,double w)
    {
    	e[++ecnt].to=t,e[ecnt].w=w;
    	e[ecnt].ne=he[f],he[f]=ecnt;
    	e[++ecnt].to=f,e[ecnt].w=0;
    	e[ecnt].ne=he[t],he[t]=ecnt;
    }
    int head[N],dep[N];
    queue<int>q;
    bool ins[N];
    bool bfs(int sp,int ep)
    {
    	memcpy(head,he,sizeof(head));
    	memset(dep,0x3f,sizeof(dep));
    	dep[sp]=1,q.push(sp);
    	while(!q.empty())
    	{
    		int x=q.front();q.pop();
    		for(int ei=he[x],t=e[ei].to;ei;ei=e[ei].ne,t=e[ei].to)
    		if(dep[t]==inf&&e[ei].w>eps) dep[t]=dep[x]+1,q.push(t);
    	}
    	return dep[ep]!=inf;
    }
    double dfs(int x,double lim,int ep)
    {
    	if(x==ep||lim<eps) return lim;
    	double ret=0,tmp=0;
    	for(int ei=head[x],t=e[ei].to;ei;ei=e[ei].ne,t=e[ei].to)
    	{
    		head[x]=ei;
    		if(dep[t]==dep[x]+1)if((tmp=dfs(t,min(e[ei].w,lim),ep))>eps)
    		{
    			lim-=tmp,ret+=tmp;
    			e[ei].w-=tmp,e[ei^1].w+=tmp;
    			if(lim<eps) break;
    		}
    	}
    	return ret;
    }
    double dinic(int sp,int ep)
    {
    	double ret=0;
    	while(bfs(sp,ep)) ret+=dfs(sp,dinf,ep);
    	return ret;
    }
    int n,m;
    int lx[N],ly[N];
    int maid()
    {
    	while(~scanf("%d%d",&n,&m))
    	{
    		if(!m){puts("1");puts("1");continue;}
    		for(int i=1;i<=m;i++) scanf("%d%d",&lx[i],&ly[i]);
    		double ansl=0,ansr=m,ansm=0,eeps=1.0/n/n;
    		while(ansr-ansl>eeps)
    		{
    			ansm=(ansl+ansr)/2;
    			for(int i=1;i<=m;i++) addline(n+i,lx[i],1.0),addline(n+i,ly[i],1.0);
    			for(int i=1;i<=m;i++) addline(n+m+1,n+i,1.0);
    			for(int i=1;i<=n;i++) addline(i,n+m+2,ansm);
    			double tmp=dinic(n+m+1,n+m+2);
    			if((double)m-tmp>eps) ansl=ansm;
    			else ansr=ansm;
    			ecnt=1,memset(he,0,sizeof(he));
    		}
    		ansm=ansl;
    		for(int i=1;i<=m;i++) addline(n+i,lx[i],dinf),addline(n+i,ly[i],dinf);
    		for(int i=1;i<=m;i++) addline(n+m+1,n+i,1.0);
    		for(int i=1;i<=n;i++) addline(i,n+m+2,ansm);
    		dinic(n+m+1,n+m+2);
    		bfs(n+m+1,n+m+2);
    		int ans=0;
    		for(int i=1;i<=n;i++) if(dep[i]!=inf) ans++;
    		printf("%d
    ",ans);
    		for(int i=1;i<=n;i++) if(dep[i]!=inf) printf("%d
    ",i);
    		ecnt=1,memset(he,0,sizeof(he));
    	}
    	return 0;
    }
    }
    int main(){return LarjaIX::maid();}
    
  • 相关阅读:
    XNA中的中文输入(三)
    0.033秒的艺术 测试程序性能
    0.033秒的艺术 List.Sort以及快速排序
    从Demo到Engine(二) Render Queue Sort
    Bounding Volume Performance Test:AABB vs OBB vs Sphere
    0.033秒的艺术 Radix Sort
    从Demo到Engine(一) IRenderable
    0.033秒的艺术 for vs. foreach
    XNA中的中文输入(一)
    0.033秒的艺术 XNA数学库中的陷阱
  • 原文地址:https://www.cnblogs.com/rikurika/p/11938295.html
Copyright © 2011-2022 走看看