zoukankan      html  css  js  c++  java
  • poj 3155 最大密度子图

    思路:

    这个还是看的胡伯涛的论文《最小割在信息学竞赛中的应用》。是将最大密度子图问题转化为了01分数规划和最小割问题。

    直接上代码:

    #include <iostream>
    #include <stdio.h>
    #include <string.h>
    #include <algorithm>
    #include <vector>
    #define Maxn 6010
    #define Maxm 200000
    #define LL double
    #define inf 100000000
    #define Abs(a) (a)>0?(a):(-a)
    using namespace std;
    struct Edge{
        int from,to,next;
        LL val;
    }edge[Maxm];
    const double eps=1e-5;
    LL value[Maxn];
    int head[Maxn],work[Maxn],dis[Maxn],q[Maxn],e,vi[Maxn];
    inline void addedge(int from,int to,LL val)//有向边
    {
        edge[e].from=from;
        edge[e].to=to;
        edge[e].val=val;
        edge[e].next=head[from];
        head[from]=e++;
        edge[e].from=to;
        edge[e].to=from;
        edge[e].val=0;
        edge[e].next=head[to];
        head[to]=e++;
    }
    inline double min(double a,double b)
    {
        return a>b?b:a;
    }
    void init()
    {
        e=0;
        memset(head,-1,sizeof(head));
    }
    void add(int u,int v,LL c)
    {
        edge[e].to=v;edge[e].val=c;edge[e].next=head[u];head[u]=e++;
        edge[e].to=u;edge[e].val=0;edge[e].next=head[v];head[v]=e++;
    }
    int bfs(int S,int T)
    {
        int rear=0;
        memset(dis,-1,sizeof(dis));
        dis[S]=0;q[rear++]=S;
        for(int i=0;i<rear;i++)
        {
            for(int j=head[q[i]];j!=-1;j=edge[j].next)
            {
                if(edge[j].val>0&&dis[edge[j].to]==-1)
                {
                    dis[edge[j].to]=dis[q[i]]+1;
                    q[rear++]=edge[j].to;
                    if(edge[j].to==T) return 1;
                }
            }
        }
        return 0;
    }
    LL dfs(int cur,LL a,int T)
    {
        if(cur==T) return a;
        for(int i=work[cur];i!=-1;i=edge[i].next)
        {
            if(edge[i].val>0&&dis[edge[i].to]==dis[cur]+1)
            {
                LL t=dfs(edge[i].to,min(a,edge[i].val),T);
                if(t>0)
                {
                    edge[i].val-=t;
                    edge[i^1].val+=t;
                    return t;
                }
            }
        }
        return 0;
    }
    LL Dinic(int S,int T)
    {
        LL ans=0;
        while(bfs(S,T))
        {
            memcpy(work,head,sizeof(head));
            LL t=dfs(S,inf,T);
            while(t>0)
            {
                ans+=t;
                t=dfs(S,inf,T);
            }
        }
        return ans;
    }
    
    int main()
    {
        int n,m,i,j,a[Maxn],b[Maxn];
        int degree[Maxn];
        memset(degree,0,sizeof(degree));
        while(scanf("%d%d",&n,&m)!=EOF)
        {
        if(m==0)
        {
            printf("1
    1
    ");
            return 0;
        }
        init();
        for(i=1;i<=m;i++)
        {
            scanf("%d%d",a+i,b+i);
            degree[a[i]]++;
            degree[b[i]]++;
        }
        double l=0,r=m,mid;
        double eps2=1.0/n/n;
        while(r-l>eps2)
        {
            mid=(l+r)/2;
            init();
            for(i=1;i<=m;i++)
            {
                add(a[i],b[i],1);
                add(b[i],a[i],1);
            }
            for(i=1;i<=n;i++)
            {
                add(0,i,m);
                add(i,n+1,m * 1.0 + 2 * mid - degree[i] * 1.0);
    
            }
            double tt=Dinic(0,n+1);
            double temp=(m*n*1.0-tt)/2.0;
            //cout<<tt<<endl;
            if(temp>eps)
                l=mid;
            else
                r=mid;
        }
        init();
        for(i=1;i<=m;i++)
        {
            add(a[i],b[i],1);
            add(b[i],a[i],1);
        }
        for(i=1;i<=n;i++)
        {
            add(0,i,m);
            add(i,n+1,m*1.0+2*l-degree[i]*1.0);
            //cout<<m<<" "<<mid<<" "<<degree[i]<<" "<<m+2*mid-degree[i]<<endl;
        }
        //for(i=0;i<e;i++)
            //cout<<edge[i].to<<" "<<edge[i].next<<" "<<edge[i].val<<endl;
        Dinic(0,n+1);
        vector<int> ans;
        memset(vi,0,sizeof(vi));
        for(i=1;i<=n;i++)
            if(dis[i]>=0)
                ans.push_back(i);
        int num=ans.size();
        printf("%d
    ",num);
        for(i=0;i<num;i++)
            printf("%d
    ",ans[i]);
        }
        return 0;
    }
  • 相关阅读:
    Pandas
    numpy常用举例
    scikit-learn 应用
    numpy基本函数
    pytong下安装安装SK-Learn
    python 在机器学习中应用函数
    决策树实战
    KNN 实战
    Java中的stream流的概念解析
    Struts2为什么要使用OGNL
  • 原文地址:https://www.cnblogs.com/wangfang20/p/3206710.html
Copyright © 2011-2022 走看看