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\n",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\n",l,r,mid);
        if(check(mid)) ans=max(ans,mid),l=mid+eps;
        else r=mid-eps;
    }
    //printf("hi %lf\n",l);
    check(ans);
    bfsSol();
    int num=0;
    for(int i=1;i<=n;i++) if(vis[i]) num++;
    printf("%d\n",num);
    for(int i=1;i<=n;i++) if(vis[i]) printf("%d\n",i);
}
int main(){
    //freopen("in.txt","r",stdin);
    n=read();m=read();s=0;t=n+m+1;
    if(!m){printf("1\n1");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\n",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\n",ans);
    for(int i=1;i<=n;i++) if(vis[i]) printf("%d\n",i);
}
int main(){
    //freopen("in","r",stdin);
    n=read();m=read();
    if(!m){printf("1\n1");return 0;}     
    s=0;t=n+m+1;
    for(int i=1;i<=m;i++) u[i]=read(),v[i]=read();
    solve();
}

 

 
 
posted @ 2017-02-23 12:21  Candy?  阅读(574)  评论(0编辑  收藏  举报