zoukankan      html  css  js  c++  java
  • POJ 3155 Hard Life(最大密度子图)

    裸题。输入一个无向图,输出最大密度子图(输出子图结点数和升序编号)。

    看了《最小割模型在信息学竞赛中的应用——胡伯涛》的一部分,感觉01分数规划问题又是个大坑。暂时还看不懂。

    参考http://blog.csdn.net/power721/article/details/6781518

    构图:

    把原图中的无向边转换成两条有向边,容量为1

    设一源点,连接所有点,容量为U(取m)。

    设一汇点,所有点连接汇点,容量为 U+2g-dv 

    二分枚举最大密度g,其中dvv的度。

    判断(U*n-MaxFlow)/2.>=0

    最后跳出的L就是最大密度。

    拿这个L再重新建图,求最大流。

    然后从s出发bfs或者dfs,走残留容量大于0的边,所有能到达的点就是答案。

    具体分析过程见胡伯涛的论文《最小割模型在信息学竞赛中的应用》

    #include <cstdio>
    #include <cstring>
    #include <iostream>
    #include <cmath>
    #include <algorithm>
    #include <vector>
    #include <string>
    #include <set>
    #include <queue>
    using namespace std;
    
    #define ll long long
    #define MP make_pair
    
    #define mxn 110
    #define mxe 4500
    #define inf 1e9
    #define eps 1e-8
    
    vector<int>ans;
    
    struct SAP{
    	int dis[mxn],pre[mxn],gap[mxn],arc[mxn];
    	double f[mxe],cap[mxe];
    	int head[mxn],nxt[mxe],vv[mxe],e;
    	void init(){e=0;memset(head,-1,sizeof(head));}
    	void add(int u,int v,double c){
    		vv[e]=v,cap[e]=c,nxt[e]=head[u],head[u]=e++;
    		vv[e]=u,cap[e]=0,nxt[e]=head[v],head[v]=e++;
    	}
    	void bfs(int s){
    		int q[mxn];
    		int ht=0,tl=0;
    		q[tl++]=s;
    		ans.clear();
    		bool vis[mxn];
    		memset(vis,false,sizeof(vis));
    		vis[s]=true;
    		while(ht<tl){
    			int u = q[ht++];
    			for(int i=head[u];i!=-1;i=nxt[i]){
    				int v = vv[i];
    				if(!vis[v] && cap[i]-f[i]){
    					vis[v]=true;
    					q[tl++]=v;
    					if(v<s) ans.push_back(v);
    				}
    			}
    		}
    	}
    	double max_flow(int s,int t,int n){
    		int q[mxn],j,mindis;
    		double ans=0;
    		int ht=0,tl=1,u,v;
    		double low;
    		bool found,vis[mxn];
    		memset(dis,0,sizeof(dis));
    		memset(gap,0,sizeof(gap));
    		memset(vis,0,sizeof(vis));
    		memset(arc,-1,sizeof(arc));
    		memset(f,0,sizeof(f));
    		q[0]=t;vis[t]=true;dis[t]=0;gap[0]=1;
    		while(ht<tl){
    			u=q[ht++];
    			for(int i=head[u];i!=-1;i=nxt[i]){
    				v = vv[i];
    				if(!vis[v]){
    					vis[v]=true;
    					dis[v]=dis[u]+1;
    					q[tl++]=v;
    					gap[dis[v]]++;
    					arc[v]=head[v];
    				}
    			}
    		}
    		u=s;low=inf;pre[s]=s;
    		while(dis[s]<n){
    			found=false;
    			for(int &i=arc[u];i!=-1;i=nxt[i]){
    				if(dis[vv[i]]==dis[u]-1 && cap[i]>f[i]){
    					found=true;v=vv[i];
    					low=min(low,cap[i]-f[i]);
    					pre[v]=u;u=v;
    					if(u==t){
    						while(u!=s){
    							u=pre[u];
    							f[arc[u]]+=low;
    							f[arc[u]^1]-=low;
    						}
    						ans+=low;low=inf;
    					}
    					break;
    				}
    			}
    			if(found) continue;
    			mindis=n;
    			for(int i=head[u];i!=-1;i=nxt[i]){
    				if(mindis>dis[vv[i]] && cap[i]>f[i]){
    					mindis=dis[vv[j=i]];
    					arc[u]=i;
    				}
    			}
    			if(--gap[dis[u]]==0) return ans;
    			dis[u]=mindis+1;
    			gap[dis[u]]++;
    			u=pre[u];
    		}
    		return ans;
    	}
    }sap;
    int e[1010][2];
    int deg[110];
    int n,m;
    bool jud(double g){
    	sap.init();
    	for(int i=0;i<m;++i){
    		sap.add(e[i][0],e[i][1],1);
    		sap.add(e[i][1],e[i][0],1);
    	}
    	for(int i=1;i<=n;++i) sap.add(n+1,i,m);
    	for(int i=1;i<=n;++i) sap.add(i,n+2,m+2*g-deg[i]);
    	double mf = sap.max_flow(n+1,n+2,n+2);
    	return (n*m-mf)/2>eps;
    }
    int main(){
    	while(~scanf("%d%d",&n,&m)){
    		if(m==0){
    			puts("1");
    			puts("1");
    			continue;
    		}
    		memset(deg,0,sizeof(deg));
    		for(int i=0;i<m;++i){
    			scanf("%d%d",&e[i][0],&e[i][1]);
    			deg[e[i][0]]++;
    			deg[e[i][1]]++;
    		}
    		double l=0,r=m;
    		while(r-l>eps){
    			double mid = (l+r)/2;
    			if(jud(mid)) l=mid;
    			else r=mid;
    		}
    		//printf("%lf
    ",l);
    		jud(l);
    		sap.bfs(n+1);
    		sort(ans.begin(),ans.end());
    		printf("%d
    ",ans.size());
    		for(int i=0;i<ans.size();++i) printf("%d
    ",ans[i]);
    	}
    	return 0;
    }
    
  • 相关阅读:
    Azure HPC Pack Cluster添加辅助节点
    Azure HPC Pack 辅助节点模板配置
    Azure HPC Pack配置管理系列(PART6)
    Windows HPC Pack 2012 R2配置
    Azure HPC Pack 节点提升成域控制器
    Azure HPC Pack VM 节点创建和配置
    Azure HPC Pack 部署必要条件准备
    Azure HPC Pack 基础拓扑概述
    Azure VM 性能计数器配置
    Maven私仓配置
  • 原文地址:https://www.cnblogs.com/nextbin/p/4064195.html
Copyright © 2011-2022 走看看