zoukankan      html  css  js  c++  java
  • poj 3308 (最大流)

    题意:n*m的地图,给出L个火星人登陆的坐标,要在火星人登陆地球的瞬间全部消灭他们,有一种激光枪,一次可以消灭一行(或一列),消灭一行(或一列)有不同的代价,总代价是所有激光枪的代价之积。

    思路:之前做过类似的题是求最少多少次能消灭,而最少的次数不一定是代价最小的,行跟列建立二分图,每个火星人就是一条边,就是选一些点覆盖所有的边,这些点的权值之积最小,如果是求和的话就是二分图的最小点权覆盖集了,所以要把求积转化成求和,a*b=log(a)+log(b);求出最小割就可以了。






    #include<stdio.h>
    #include<math.h>
    #include<string.h>
    const int N=3000;
    #define inf 100.0
    int head[N],num,ans,start,end,gap[N],dis[N];
    struct edge
    {
    	int st,ed,next;
    	double flow;
    }e[N*100];
    void addedge(int x,int y,double w)
    {
    	e[num].st=x;e[num].ed=y;e[num].flow=w;e[num].next=head[x];head[x]=num++;
    	e[num].st=y;e[num].ed=x;e[num].flow=0;e[num].next=head[y];head[y]=num++;
    }
    double dfs(int u,double minflow)
    {
    	if(u==end)return minflow;
    	int i,v;
    	double f,flow=0.0;
    	for(i=head[u];i!=-1;i=e[i].next)
    	{
    		v=e[i].ed;
    		if(e[i].flow>0)
    		{
    			if(dis[v]+1==dis[u])
    			{
    				f=dfs(v,e[i].flow>minflow-flow?minflow-flow:e[i].flow);
    				flow+=f;
    				e[i].flow-=f;
    				e[i^1].flow+=f;
    				if(minflow-flow<=1e-8)return flow;  
    				if(dis[start]>=ans)return flow;  
    			}
    		}
    	}
    	if(--gap[dis[u]]==0)
    		dis[start]=ans;
    	dis[u]++;
    	gap[dis[u]]++;
    	return flow;
    }
    double isap()
    {
    	double maxflow=0.0;
    	memset(gap,0,sizeof(gap));
    	memset(dis,0,sizeof(dis));
    	gap[0]=ans;
    	while(dis[start]<ans)
    		maxflow+=dfs(start,inf);
    	return maxflow;	
    }
    int main()
    {
    	int i,n,m,k,x,y,t;
    	double w;
    	scanf("%d",&t);
    	while(t--)
    	{
    		scanf("%d%d%d",&n,&m,&k);
    		memset(head,-1,sizeof(head));
    		num=0;start=0;end=n+m+1;ans=end+1;
    		for(i=1;i<=n;i++)
    		{
    			scanf("%lf",&w);
    			addedge(start,i,log(w));
    		}
    		for(i=1;i<=m;i++)
    		{
    			scanf("%lf",&w);
    			addedge(i+n,end,log(w));
    		}
    		while(k--)
    		{
    			scanf("%d%d",&x,&y);
    			addedge(x,y+n,inf);
    		}
    		w=isap();
    		printf("%.4lf
    ",exp(w));
    	}
    	return 0;
    }


  • 相关阅读:
    Webpack的学习总结(1)
    mybatis-plus逻辑删除
    vscode编译调试C/C++多文件——linux(makefile)
    vscode配置调试C/C++程序——linux环境(命令行编译)
    shell编程题(二十二)
    shell编程题(二十三)
    shell编程题(二十一)
    shell编程题(二十)
    GTK开发视频播放器
    C语言实现LRU缓存(二)
  • 原文地址:https://www.cnblogs.com/suncoolcat/p/3339543.html
Copyright © 2011-2022 走看看