zoukankan      html  css  js  c++  java
  • POJ3155 Hard Life [最大密度子图]

     
    题意:最大密度子图

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int N=1105,M=4005,INF=1e9;
    const double eps=1e-6;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    int n,m,u[N],v[N],s,t;
    struct edge{
        int v,ne;
        double c,f;
    }e[M<<1];
    int cnt,h[N];
    inline void ins(int u,int v,double c){
        cnt++;
        e[cnt].v=v;e[cnt].c=c;e[cnt].f=0;e[cnt].ne=h[u];h[u]=cnt;
        cnt++;
        e[cnt].v=u;e[cnt].c=0;e[cnt].f=0;e[cnt].ne=h[v];h[v]=cnt;
    }
    int cur[N],d[N],vis[N];
    int q[N],head,tail;
    bool bfs(){
        head=tail=1;
        memset(vis,0,sizeof(vis));
        d[s]=1;vis[s]=1;q[tail++]=s;
        while(head!=tail){
            int u=q[head++];
            for(int i=h[u];i;i=e[i].ne){
                int v=e[i].v;
                if(!vis[v]&&e[i].c>e[i].f){
                    vis[v]=1;d[v]=d[u]+1;
                    q[tail++]=v;
                    if(v==t) return true;
                }
            }
        }
        return false;
    }
    double dfs(int u,double a){
        if(u==t||a==0) return a;
        double flow=0,f;
        for(int &i=cur[u];i;i=e[i].ne){
            int v=e[i].v;
            if(d[v]==d[u]+1&&(f=dfs(v,min(e[i].c-e[i].f,a)))>0){
                flow+=f;
                e[i].f+=f;
                e[((i-1)^1)+1].f-=f;
                a-=f;
                if(a==0) break;
            }
        }
        if(a) d[u]=-1;
        return flow;
    }
    double dinic(){
        double flow=0;
        while(bfs()){
            for(int i=s;i<=t;i++) cur[i]=h[i];
            flow+=dfs(s,INF);
        }
        //printf("dinic %lf
    ",flow);
        return flow;
    }
    
    void bfsSol(){
        head=tail=1;
        memset(vis,0,sizeof(vis));
        q[tail++]=s;vis[s]=1;
        while(head!=tail){
            int u=q[head++];
            for(int i=h[u];i;i=e[i].ne){
                int v=e[i].v;
                if(!vis[v]&&e[i].c>e[i].f){
                    vis[v]=1;
                    q[tail++]=v;
                }
            }
        }
    }
    
    bool check(double x){
        cnt=0;
        memset(h,0,sizeof(h));
        for(int i=1;i<=n;i++) ins(i,t,x);
        for(int i=1;i<=m;i++){
            ins(s,n+i,1);
            ins(n+i,u[i],INF);
            ins(n+i,v[i],INF);
        }
        return m-dinic()>eps;//eps
    }
    void solve(){
        double l=1.0/n,r=m,eps=1.0/(n*n),ans=0;
        while(r-l>eps){
            double mid=(l+r)/2;//printf("erfen %lf %lf %lf
    ",l,r,mid);
            if(check(mid)) ans=max(ans,mid),l=mid+eps;
            else r=mid-eps;
        }
        //printf("hi %lf
    ",l);
        check(ans);
        bfsSol();
        int num=0;
        for(int i=1;i<=n;i++) if(vis[i]) num++;
        printf("%d
    ",num);
        for(int i=1;i<=n;i++) if(vis[i]) printf("%d
    ",i);
    }
    int main(){
        //freopen("in.txt","r",stdin);
        n=read();m=read();s=0;t=n+m+1;
        if(!m){printf("1
    1");return 0;} 
        for(int i=1;i<=m;i++) u[i]=read(),v[i]=read();
        solve();
    }
     
    
     
    1月24日代码..二分各种处理精度

    今天又写了一次,只要$dinic$中判断$a==0$加一个精度就可以过了...

    另一种做法不学了...

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<algorithm>
    #include<cmath>
    using namespace std;
    const int N=1105,M=4005,INF=1e9;
    const double eps=1e-6;
    inline int read(){
        char c=getchar();int x=0,f=1;
        while(c<'0'||c>'9'){if(c=='-')f=-1; c=getchar();}
        while(c>='0'&&c<='9'){x=x*10+c-'0'; c=getchar();}
        return x*f;
    }
    int n,m,u[N],v[N],s,t;
    struct edge{
        int v,ne;
        double c,f;
    }e[M<<1];
    int cnt,h[N];
    inline void ins(int u,int v,double c){
        cnt++;
        e[cnt].v=v;e[cnt].c=c;e[cnt].f=0;e[cnt].ne=h[u];h[u]=cnt;
        cnt++;
        e[cnt].v=u;e[cnt].c=0;e[cnt].f=0;e[cnt].ne=h[v];h[v]=cnt;
    }
    bool vis[N];
    int d[N],q[N],head,tail;
    int cur[N];
    bool bfs(){
        memset(vis,0,sizeof(vis));
        head=tail=1;
        d[s]=0;vis[s]=1;q[tail++]=s;
        while(head!=tail){
            int u=q[head++];
            for(int i=h[u];i;i=e[i].ne){
                int v=e[i].v;
                if(!vis[v]&&e[i].c>e[i].f){
                    vis[v]=1;
                    q[tail++]=v;
                    d[v]=d[u]+1;
                    if(v==t) return true;
                }
            }
        }
        return false;
    }
    double dfs(int u,double a){
        if(u==t||abs(a)<eps) return a;
        double flow=0,f;
        for(int &i=cur[u];i;i=e[i].ne){
            int v=e[i].v;
            if(d[v]==d[u]+1&&(f=dfs(v,min(e[i].c-e[i].f,a)))>0){
                flow+=f;
                e[i].f+=f;
                e[((i-1)^1)+1].f-=f;
                a-=f;
                if(a==0) break;
            }
        }
        if(a) d[u]=-1;
        return flow;
    }
    double dinic(){
        double flow=0;
        while(bfs()){
            for(int i=s;i<=t;i++) cur[i]=h[i];
            flow+=dfs(s,INF);
        }
        return flow;
    }
    void bfsSol(){
        memset(vis,0,sizeof(vis));
        head=tail=1;
        q[tail++]=s;
        while(head!=tail){
            int u=q[head++];
            for(int i=h[u];i;i=e[i].ne)
                if(!vis[e[i].v]&&e[i].c>e[i].f)
                    vis[e[i].v]=1,q[tail++]=e[i].v;
        }
    }
    bool check(double g){
        cnt=0;memset(h,0,sizeof(h));
        for(int i=1;i<=n;i++) ins(i,t,g);
        for(int i=1;i<=m;i++) ins(s,n+i,1),ins(n+i,u[i],INF),ins(n+i,v[i],INF);
        return m-dinic()>eps;
    }
    void solve(){
        double l=1.0/n,r=m,eps=1.0/n/n;
        while(r-l>eps){
            double mid=(l+r)/2.0;//printf("mid %lf %lf %lf
    ",l,r,mid);
            if(check(mid)) l=mid;
            else r=mid;
        }
        check(l);
        bfsSol();
        int ans=0;
        for(int i=1;i<=n;i++) if(vis[i]) ans++;
        printf("%d
    ",ans);
        for(int i=1;i<=n;i++) if(vis[i]) printf("%d
    ",i);
    }
    int main(){
        //freopen("in","r",stdin);
        n=read();m=read();
        if(!m){printf("1
    1");return 0;}     
        s=0;t=n+m+1;
        for(int i=1;i<=m;i++) u[i]=read(),v[i]=read();
        solve();
    }
     
     
  • 相关阅读:
    微信 token ticket jsapi_ticket access_token 获取 getAccessToken get_jsapi_ticket方法
    PHP 日志 记录 函数 支持 数组 对象 新浪 sae 环境 去掉 空格 换行 格式化 输出 数组转字符串
    原生 原始 PHP连接MySQL 代码 参考mysqli pdo
    PHP 数字金额转换成中文大写金额的函数 数字转中文
    使用PHPMailer发送带附件并支持HTML内容的邮件
    设置输出编码格式 header 重定向 执行时间 set_time_limit 错误 报告 级别 error_reporting
    html5 bootstrap pannel table 协议 公告 声明 文书 模板
    指向指针的指针
    二级指针
    c语言:当指针成为参数后
  • 原文地址:https://www.cnblogs.com/candy99/p/6347810.html
Copyright © 2011-2022 走看看