#9 //[SDOI2017]新生舞会

题解:

分数规划+费用流

常数巨大开o2加inline加register还是不行

我也不知道为什么

代码:

#include <bits/stdc++.h>
using namespace std;
const int N=5e4;
const int N1=2e3;
#define INF 1e9
#define INF2 1e4
#define eps 1e-7
#define rg register
#define IL inline
int pre[N],aa[N],s,t,n,m;
double dis[N];
bool vis[300];
int l,p1[N1][N1],p2[N1][N1],head[10000];
struct re{
    int a,b,c,flow,from;
    double cost;
}a[N];
IL void arr(int x,int y,int z,int flow,double cost)
{
     a[++l].a=head[x];
     a[l].b=y;
     a[l].c=z;
     a[l].flow=flow;
     a[l].from=x;
     a[l].cost=cost;
     head[x]=l;
}
IL bool bellmanford(double &flow,double &cost)
{
      queue<int>q;
    for (rg int i=1;i<=t;i++) dis[i]=INF;
    aa[s]=INF;
    memset(vis,1,sizeof(vis));
    q.push(s);
    while (!q.empty())
    {
        rg int x=q.front(); q.pop();
        rg int u=head[x];
        while (u)
        {
          rg  int v=a[u].b;
          if (dis[x]+a[u].cost<dis[v]&&a[u].c>a[u].flow)
          {
               dis[v]=dis[x]+a[u].cost;
               aa[v]=min(aa[x],a[u].c-a[u].flow);
               pre[v]=u;
               if (vis[v])
               {
                     vis[v]=0; q.push(v);
                 }
          }
          u=a[u].a;
        }
        vis[x]=1;
    }
    if (dis[t]==INF) return(0);
    rg int x=t; flow+=aa[t]; cost+=aa[t]*dis[t];
    while (pre[x])
    {
        rg int y=pre[x];
        a[y].flow+=aa[t];
        if (y%2==1) a[y+1].flow-=aa[t];
               else a[y-1].flow-=aa[t];
        x=a[y].from;
    }
    return 1;
}
double flow,cost;
IL void mincost()
{
    while (bellmanford(flow,cost));
}
#define mid (h+t)/2
IL bool check(double x)
{
    l=0;
    memset(head,0,sizeof(head));
    for (rg int i=1;i<=n;i++)
      for (rg int j=1;j<=n;j++)
      {
          arr(i,j+n,1,0,-(p1[i][j]-p2[i][j]*x));
          arr(j+n,i,0,0,(p1[i][j]-p2[i][j]*x));
        }
    s=0,t=2*n+1;
    for (rg int i=1;i<=n;i++)
    {
        arr(0,i,1,0,0); arr(i,0,0,0,0);
        arr(i+n,t,1,0,0); arr(t,i+n,0,0,0);
    }
    flow=0; cost=0;
    mincost();
    if (cost<=0) return(1);
    else return(0);
}
int main()
{
    std::ios::sync_with_stdio(false);
    cin>>n;
    for (rg int i=1;i<=n;i++)
      for (rg int j=1;j<=n;j++)
        cin>>p1[i][j];
    for (rg int i=1;i<=n;i++)
      for (rg int j=1;j<=n;j++)
        cin>>p2[i][j];
    double h=0,t=INF2;
    while (t-h>eps)
    {
        if (check(mid)) h=mid;
        else t=mid;
    }
    printf("%.6f",h);
    return 0;
}

 

posted @ 2018-04-24 14:19  尹吴潇  阅读(194)  评论(0编辑  收藏  举报