poj 3155 Hard Life 最大密度子图

//poj 3155
//sep9
#include <iostream>  
#include <queue>  
  
using namespace std;  
const int MAXN=512;  
const int MAXM=20000;
const double MAX=1e7;  
typedef double cap_type;
  
struct Edge  
{  
    int v,nxt;
	cap_type f;  
}e[MAXM];  
  
queue<int> que;  
int src,sink;  
int g[MAXN],dist[MAXN];  
int nume;  
  
int n,m,sum;
int degree[MAXN],px[MAXM],py[MAXM];
bool vis[MAXN];  
  
void addedge(int u,int v,cap_type c)  
{  
    e[++nume].v=v;e[nume].f=c;e[nume].nxt=g[u];g[u]=nume;        
    e[++nume].v=u;e[nume].f=0;e[nume].nxt=g[v];g[v]=nume;    
}  
  
void init()        
{        
    memset(g,0,sizeof(g));          
    nume=1;        
}        
        
int bfs()        
{        
    while(!que.empty()) que.pop();        
    memset(dist,-1,sizeof(dist));  
	dist[src]=0;                     
    que.push(src);          
    while(!que.empty()){        
        int u=que.front();que.pop();        
        for(int i=g[u];i;i=e[i].nxt)        
            if(e[i].f>0&&dist[e[i].v]<0){        
                que.push(e[i].v);        
                dist[e[i].v]=dist[u]+1;           
                if(e[i].v==sink)        
                    return 1;        
            }        
    }        
    return 0;        
}    
  
cap_type dfs(int u,cap_type delta)        
{        
    if(u==sink)        
        return delta;        
    cap_type ret=0;        
    for(int i=g[u];i;i=e[i].nxt)        
        if(e[i].f>0&&dist[e[i].v]==dist[u]+1){        
            cap_type dd=dfs(e[i].v,min(e[i].f,delta));        
            if(dd>0){        
                e[i].f-=dd;        
                e[i^1].f+=dd;        
                ret+=dd;
				delta-=dd;        
            }        
            else        
                dist[e[i].v]=-1;        
        }           
    return ret;        
}           
  
cap_type dinic()        
{        
    cap_type ret=0;        
    while(bfs()==1)        
        ret+=dfs(src,MAX);        
    return ret;         
}     
  
void dfs_travel(int u)
{
	++sum;
	vis[u]=1;
    for(int i=g[u];i;i=e[i].nxt)        
    	if(e[i].f>0&&!vis[e[i].v])
    		dfs_travel(e[i].v);
}

void construct_graph(double g)
{
	init();
	for(int i=1;i<=n;++i){
		addedge(src,i,m);
		addedge(i,sink,m+2*g-degree[i]);
	}
	for(int i=0;i<m;++i){
		addedge(px[i],py[i],1.0);
		addedge(py[i],px[i],1.0);
	}	
}

int main()  
{  
	scanf("%d%d",&n,&m);
	if(m==0){
		puts("1\n1\n");	
		return 0;
	}
	memset(degree,0,sizeof(degree));
	for(int i=0;i<m;++i){
		scanf("%d%d",&px[i],&py[i]);
		++degree[px[i]];
		++degree[py[i]];
	}
	src=0,sink=n+1;
	double lb=0.0,ub=m*1.0,mid,h;
	double precision = 1.0/n/n;
	while(ub-lb>=precision){
		mid=(ub+lb)/2;
		construct_graph(mid);
		h=(n*m-dinic())/2;
		(h>0?lb:ub)=mid;
	}
	construct_graph(lb);
	dinic();
	sum=0;
	memset(vis,0,sizeof(vis));
	dfs_travel(0);
	printf("%d\n",sum-1);
	for(int i=1;i<=n;++i)
		if(vis[i])
			printf("%d\n",i);	
}  

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值