Uvalive 7037 The Problem Needs 3D Arrays(最大密度子图)

来源:互联网 发布:java编写图书管理系统 编辑:程序博客网 时间:2024/05/16 12:33

题目地址:https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=5049

思路:逆序对个数除以序列长度。类比最大密度子图边数除以点数。则若<i,j>为一逆序对,则连边<i,j>。则边数为逆序对个数,点数为序列长度,求出最大密度子图即可。

#include<cstdio>#include<cstring>#include<iostream>#include<algorithm>#define debuusing namespace std;const double eps=1e-7;const int INF=0x3f3f3f3f;const int maxn=1e4+50;const int maxm=5e4+50;int n,tot,s,t,num;int adj[maxn],dis[maxn];int a[maxn],q[maxn],d[maxn];struct edge{    int v,pre;    double w;} e[maxm];struct node{    int u,v;} E[maxn];void Insert(int u,int v,double w){    e[num]=(edge){v,adj[u],w},adj[u]=num++;    e[num]=(edge){u,adj[v],0},adj[v]=num++;}int bfs(){    int i,x,v,head=0,tail=0;    memset(dis,0,sizeof(dis));    dis[s]=1;    q[++tail]=s;    while(head!=tail)    {        x=q[head=(head+1)%maxn];        for(i=adj[x]; ~i; i=e[i].pre)            if(e[i].w>0&&!dis[v=e[i].v])            {                dis[v]=dis[x]+1;                if(v==t) return 1;                q[tail=(tail+1)%maxn]=v;            }    }    return 0;}double dfs(int x,double limit){    if(x==t) return limit;    int v;    double tmp,cost=0;    for(int i=adj[x]; ~i&&cost<limit; i=e[i].pre)        if(e[i].w>0&&dis[x]==dis[v=e[i].v]-1)        {            tmp=dfs(v,min(limit-cost,e[i].w));            if(tmp)            {                e[i].w-=tmp;                e[i^1].w+=tmp;                cost+=tmp;            }            else dis[v]=-1;        }    return cost;}double Dinic(){    double ans=0.0;    while(bfs()) ans+=dfs(s,INF);    return ans;}int ok(double mid){    memset(adj,-1,sizeof(adj));    num=0,s=0,t=n+1;    for(int i=1; i<=tot; i++)    {        Insert(E[i].v,E[i].u,1);        Insert(E[i].u,E[i].v,1);    }    for(int i=1; i<=n; i++)    {        Insert(s,i,tot);        Insert(i,t,tot*1.0+2*mid-1.0*d[i]);    }    return (1.0*tot*n-Dinic())>=eps;}int main(){#ifdef debug     freopen("in.in","r",stdin);#endif // debug    int t,cas=0;    scanf("%d",&t);    while(t--)    {        printf("Case #%d: ",++cas);        scanf("%d",&n);        tot=0;        memset(d,0,sizeof(d));        for(int i=1; i<=n; i++)            scanf("%d",&a[i]);        for(int i=1; i<=n; i++)            for(int j=i+1; j<=n; j++)            {                if(a[i]>a[j])                {                    tot++;                    E[tot].u=i;                    E[tot].v=j;                    d[i]++,d[j]++;                }            }        double l=0,r=tot,mid,ans=0.0;        while(r-l>eps)        {            mid=(l+r)/2.;            if(ok(mid))                {                    ans=mid;                    l=mid;                }            else r=mid;        }        printf("%f\n",ans);    }    return 0;}


0 0
原创粉丝点击