BZOJ 1312 Hard Life

Posted on 2017-02-12 14:07  ziliuziliu  阅读(168)  评论(0编辑  收藏  举报

就是裸题啦。

注意最后还要跑一遍网络流才是正确的图。

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<queue>
#include<cmath>
#define maxv 105
#define maxn 1005
#define maxe 1000050
#define inf 1000000007
#define eps 1e-5
using namespace std;
int n,m,x[maxn],y[maxn],nume=1,g[maxv],dis[maxv],ans=0,s,t,d[maxv];
bool vis[maxv];
struct edge
{
    int v,nxt;
    double f;
}e[maxe];
queue <int> q;
bool comp(double x,double y)
{
    if (fabs(x-y)<=eps) return 0;
    else if (x<y) return -1;
    else return 1;
}
void addedge(int u,int v,double f)
{
    e[++nume].v=v;e[nume].nxt=g[u];
    e[nume].f=f;g[u]=nume;
    e[++nume].v=u;e[nume].nxt=g[v];
    e[nume].f=0;g[v]=nume;
}
void build(double g)
{
    nume=1;
    for (int i=1;i<=n;i++) addedge(s,i,(double)m),addedge(i,t,(double)m+2*g-d[i]);
    for (int i=1;i<=m;i++) addedge(x[i],y[i],1),addedge(y[i],x[i],1);    
}
bool bfs()
{
    for (int i=s;i<=t;i++) dis[i]=inf;
    dis[s]=0;q.push(s);
    while (!q.empty())
    {
        int head=q.front();q.pop();
        for (int i=g[head];i;i=e[i].nxt)
        {
            int v=e[i].v;
            if ((comp(e[i].f,0)>0) && (dis[v]>dis[head]+1))
            {
                dis[v]=dis[head]+1;
                q.push(v);
            }
        }
    }
    return dis[t]!=inf;
}
double dinic(int x,double low)
{
    double ret=0;
    if (x==t) return low;
    for (int i=g[x];i && (comp(low,0)>0);i=e[i].nxt)
    {
        int v=e[i].v;
        if ((comp(e[i].f,0)>0) && (dis[v]==dis[x]+1))
        {
            double dd=dinic(v,min(e[i].f,low));
            ret+=dd;low-=dd;
            e[i].f-=dd;e[i^1].f+=dd;
        }
    }
    if (comp(ret,0)<=0) dis[x]=inf;
    return ret;
}
double check(double g)
{
    build(g);double max_flow=0;
    while (bfs())
        max_flow+=dinic(s,inf);
    return (double)m*n-max_flow;
}
void binary_search()
{
    double l=0,r=m,min_gap=(double)1/n/n,mid;
    while (r-l>min_gap)
    {
        memset(g,0,sizeof(g));
        mid=(l+r)/2;
        double cs=check(mid);
        if (comp(cs,0)>0) l=mid;else r=mid;
    }
    memset(g,0,sizeof(g));double cs=check(l);cs=0;
    return;
}
void find(int x)
{
    ans++;vis[x]=true;  
    for (int i=g[x];i;i=e[i].nxt)
    {
        if ((comp(e[i].f,0)>0) && (!vis[e[i].v]))
            find(e[i].v);
    }
}
int main()
{
    scanf("%d%d",&n,&m);s=0;t=n+1;
    if (!m) {printf("1\n");return 0;}
    for (int i=1;i<=m;i++)
    {
        scanf("%d%d",&x[i],&y[i]);
        d[x[i]]++;d[y[i]]++;
    }
    binary_search();
    find(s);
    printf("%d\n",ans-1);
    return 0;
}