poj 3155 (최대 밀도 서브 맵)

제목: 한 회사 에 n 명 이 있 고 충돌 이 있 는 사람들의 대수 (u, v) 를 제시 했다. 회 사 는 사람 을 자 르 기로 결정 했다. 그러면 총 재 는 지금 충돌 율 이 가장 높 은 사람들 (충돌 율 = 이들 사이 에 존재 하 는 충돌 수 / 인원) 을 자 르 려 고 한다.바로 점 을 구 하 는 것 이다. 이 점 들 사이 의 변수 / 포인트 가 가장 크다.최대 밀도 서브 맵.
사고: 후진 타 오의 논문 은 두 가지 방법 을 소개 했다.
첫 번 째: 최대 권 폐쇄 도 모델 로 전환 하여 설명 한다.
max g = f (x) = | E '| / V' | 를 설정 합 니 다. 하위 그림 의 변수 와 포인트 의 비율 이 그 중에서 가장 큽 니 다. 우 리 는 보통 함수 max h (g) = | E '| - g * V' | 를 구성 합 니 다. h (g) 가 0 일 때 g 의 값 이 가장 좋 습 니 다. h (g) > 0 일 때 g < 최 우수 치, h (g) < 0 일 때 g > 최 우수 치 입 니 다.최대 치가 0 보다 크 면 우 리 는 g 의 값 을 계속 증가 시 켜 h (g) 를 줄 일 수 있 기 때 문 입 니 다. 만약 에 최대 치가 0 보다 작 으 면 g 는 증가 할 수 없고 감소 할 수 있 습 니 다!
h (g) 를 관찰 하면 변 과 점 이 의존 관계 가 있 으 면 변 의존 점, 변 에 존재 하 는 필요 한 조건 은 점 의 존재 이다. 그러면 앞으로 우리 가 변 을 점 으로 본다 면 이것 은 가장 큰 권 폐 합 자 도 에 부합 되 지 않 을 것 이다.현재 h (g) 의 구법 은 새로운 그림 의 최대 권 폐 합 자 그림 의 값 을 구 하 는 것 을 통 해 해결 할 수 있 습 니 다. 그러나 여기 문제 가 있 습 니 다. 그림 을 만 든 후에 구 하 는 값 과 h (g) 가 원래 값 에 대응 하지 않 아야 한 다 는 것 을 알 수 있 습 니 다. (구체 적 으로 왜 이해 하지 못 하 는 지) 이렇게 이해 할 수 있 습 니 다. 가장 작은 g 이 h (g) 를 0 으로 만 들 때 가장 좋 은 것 으로 풀 어야 합 니 다. 왜냐하면 h (g)단조 로 운 체감 함수 입 니 다. 이 함수 로 볼 때 하나의 g 만 존재 할 수 있 습 니 다. h (g) = 0;그러나 최대 권 폐 합 자 도 를 구 하 는 것 은 서브 맵 의 가중치 와 0 이 많은 중 g 입 니 다. 가장 작은 g 으로 h (g) 를 0 으로 만 든 후에 g 가 계속 커지 면 최대 권 폐 합 자 도 를 통 해 구 하 는 값 은 0 이지 만 진정한 h (g) < 0 이기 때문에 가장 좋 은 해 를 얻 으 려 면 가장 큰 권 폐 합 자 도 를 만 드 는 가중치 와 0 의 가장 작은 g 값 입 니 다!이렇게 구 해 를 한 후에 원점 에서 합류 점 으로 흐 르 는 변 은 바로 최대 밀도 서브 맵 중의 점 이다.
두 번 째:
원점 에서 각 점 까지 연결 하 는 것 은 방향 변 의 가중치 가 U 이 고 각 점 에서 외환 점 까지 연결 하 는 변 의 가중치 가 U + 2 * g - d 이 며 원래 관계 가 있 는 점 연결 두 개 는 방향 변 (u, v) 이 있 으 며 (v, u) 의 가중치 가 1 (U 는 m 를 취 할 수 있 고 U 의 목적 은 2 * g - d 의 값 을 항상 플러스 로 하 는 것) 이다. 이런 다음 에 최소 로 자 르 면 h (g) = (U * n - mincut) / 2;2 점 에서 가장 좋 은 값 을 찾 으 면 mid 이지 만 그림 의 점 을 요구 하면 left 로 새 그림 에서 최대 흐름 을 구 한 다음 에 원점 에서 dfs 를 옮 겨 다 니 며 결 과 를 얻어 야 합 니 다.
첫 번 째 코드:
#include<stdio.h>
#include<string.h>
const int N=1500;
const double inf=0x3fffffff;
const double eps=1e-8;
int gap[N],dis[N],start,end,ans,sum,head[N],num,dep[N],n,m;
bool vis[N];
struct edge
{
	int st,ed,next;
	double flow;
}e[80*N];
struct node
{
	int x,y;
}P[1100];
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++;
}
void makemap(double g)
{
	int i;
	memset(head,-1,sizeof(head));
	num=0;
	for(i=1;i<=n;i++)
		addedge(i,end,g);
	for(i=0;i<m;i++)
	{
		addedge(n+i+1,P[i].y,inf);
		addedge(n+i+1,P[i].x,inf);
		addedge(start,n+i+1,1.0);
	}
}
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 1.0*m-maxflow;   
}
void dfs1(int u)
{
	vis[u]=true;
	if(u>=1&&u<=n)
	sum++;
	for(int i=head[u];i!=-1;i=e[i].next)
	{
		int v=e[i].ed;
		if(vis[v]==false&&e[i].flow>0)
		  dfs1(v);
	}
}
int main()
{
	int i;
	double Left,Right,mid,flow;
	while(scanf("%d%d",&n,&m)!=-1)
	{
		if(m==0){printf("1
1
");continue;} start=0,end=n+m+1,ans=end+1; for(i=0;i<m;i++) { scanf("%d%d",&P[i].x,&P[i].y); } Left=0;Right=m; while(Right-Left>=1.0/n/n)// , 1/(n*n) { mid=(Left+Right)/2; makemap(mid); flow=isap();// if(flow<eps)// 0,g Right=mid; else Left=mid; } makemap(Left);// isap(); memset(vis,false,sizeof(vis)); sum=0; dfs1(start); printf("%d
",sum); for(i=1;i<=n;i++) if(vis[i]==true)// printf("%d
",i); } return 0; }

두 번 째 코드:
#include<stdio.h>
#include<string.h>
const int N=110;
const double inf=0x3fffffff;
const double eps=1e-8;
int gap[N],dis[N],start,end,ans,sum,head[N],num,dep[N],n,m;
bool vis[N];
struct edge
{
	int st,ed,next;
	double flow;
}e[80*N];
struct node
{
	int x,y;
}P[1100];
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++;
}
void makemap(double g)
{
	int i;
	memset(head,-1,sizeof(head));
	num=0;
	for(i=1;i<=n;i++)
	{
		addedge(start,i,m*1.0);
		addedge(i,end,m+2*g-dep[i]);
	}
	for(i=0;i<m;i++)
	{
		addedge(P[i].x,P[i].y,1.0);
		addedge(P[i].y,P[i].x,1.0);
	}
}
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;   
}
void dfs1(int u)//      
{
	vis[u]=true;
	sum++;
	for(int i=head[u];i!=-1;i=e[i].next)
	{
		int v=e[i].ed;
		if(vis[v]==false&&e[i].flow>0)
		  dfs1(v);
	}
}
int main()
{
	int i;
	double Left,Right,mid,hg;
	while(scanf("%d%d",&n,&m)!=-1)
	{
		if(m==0){printf("1
1
");continue;} start=0,end=n+1,ans=end+1; memset(dep,0,sizeof(dep)); for(i=0;i<m;i++) { scanf("%d%d",&P[i].x,&P[i].y); dep[P[i].x]++;dep[P[i].y]++; } Left=0;Right=m; while(Right-Left>=1.0/n/n)// , 1/(n*n) { mid=(Left+Right)/2; makemap(mid); hg=isap(); hg=(1.0*n*m-hg)/2; if(hg>eps) Left=mid; else Right=mid; } makemap(Left);// mid wa, mid h(mid)>eps, Left isap(); memset(vis,false,sizeof(vis)); sum=0; dfs1(0); printf("%d
",sum-1); for(i=1;i<=n;i++) if(vis[i]==true) printf("%d
",i); } return 0; }

좋은 웹페이지 즐겨찾기