bzoj 4819: [Sdoi2017]新生舞会
2018-03-27 19:20
316 查看
题目链接
bzoj4819: [Sdoi2017]新生舞会题解
很裸的01分规,化完式子大概是这样的$ \sum ai - \sum bi *C$
二分最大比值C建图,
当最大费用 >=0 时,二分下界调大
否则上界调小
在洛谷似乎有些卡常,但借助bzoj的总时限还是跑过去了
然而开始的时候我是用$ \sum bi *C-\sum ai $这个式子做的
然后GG...调不动了.....重打
代码
#include<queue> #include<cstdio> #include<cstring> #include<algorithm> #define eps 1e-7 using std::queue; inline int read() { int x=0,f=1; char c=getchar(); while(c<'0'||c>'9') {if(c=='-')f=-1;c=getchar();} while (c<='9'&&c>='0') x=x*10+c-'0',c=getchar(); return x*f; } const int maxn = 307; int n; double a[maxn][maxn]; double b[maxn][maxn]; struct node{ int flow,u,v,next;double cost; }edge[maxn*maxn*3]; int num=1,head[maxn<<1],S,T,tmp; inline void add_edge(int u,int v,int flow,double cost) { edge[++num].u = u;edge[num].v = v;edge[num].flow = flow;edge[num].cost = cost,edge[num].next = head[u];head[u] = num; } inline void ADD(int u,int v,int flow,double cost) { add_edge(u,v,flow,cost); add_edge(v,u,0,-cost); } void rebuild(double C) { num=1; memset(head,0,sizeof head); for (int i = 1;i <= n;++i) ADD(S,i,1,0), ADD(n + i,T,1,0); for (int i = 1;i <= n;++ i) for (int j = 1;j <= n;++ j) ADD(i,n + j,1, a[i][j]-b[i][j]*C); } double dis[maxn<<2];int pre[maxn<<2];bool vis[maxn<<2]; bool spfa() { queue<int>q; for(int i=S;i<=T;++i) dis[i]=-0x3f3f3f3f,pre[i]=0; memset(vis,0,sizeof vis); q.push(S);vis[S] = true;dis[S] = 0; while (!q.empty()) { int u = q.front();q.pop(); for (int v,i = head[u];i;i = edge[i].next) { v = edge[i].v; if (edge[i].flow > 0&&dis[v] < dis[u] + edge[i].cost) { pre[v] = i; dis[v] = dis[u] + edge[i].cost; if (!vis[v]) q.push(v),vis[v] = 1; } } vis[u] = 0; } return dis[T] != -0x3f3f3f3f; } double calc() { double ret = 0;int MF = 0x3f3f3f3f; for (int i = T;i != S;i = edge[pre[i]].u) MF = std::min(edge[pre[i]].flow,MF); for (int i = T;i != S;i = edge[pre[i]].u) { edge[pre[i]].flow -= MF; edge[pre[i]^1].flow += MF; ret += edge[pre[i]].cost * 1.0*MF; } return ret; } double mfmc() { double ret=0; while(spfa()) ret += calc(); return ret; } bool check() { return mfmc()>=0 ? true : false ; } int main() { n = read(); S = 0,T = n*2+1; for (int i = 1;i <= n;++ i) for (int j = 1;j <= n;++ j) a[i][j]=read(); for (int i = 1;i <= n;++ i) for (int j = 1;j <= n;++ j) b[i][j] = read(); //printf("%lf %lf\n",dis[0],0x3f3f3f3f); double l=0,r=1000009.0; while(r - l > eps) { double mid = (l + r) / 2; rebuild(mid); if(check()) l=mid; else r=mid; } printf("%lf\n",l); return 0; }
相关文章推荐
- 【bzoj4819】[Sdoi2017]新生舞会 分数规划+费用流
- [BZOJ4819][SDOI2017]新生舞会(分数规划+费用流,KM)
- BZOJ4819 [Sdoi2017]新生舞会 【01分数规划 + 费用流】
- [BZOJ4819]-[Sdoi2017]新生舞会-01分数规划+费用流
- bzoj 4819: [Sdoi2017]新生舞会【二分+最小费用最大流】
- 【BZOJ4819】【SDOI2017】新生舞会 [费用流][分数规划]
- [bzoj4819][Sdoi2017]新生舞会
- BZOJ 4819:[Sdoi2017]新生舞会 01分数规划+费用流
- 【BZOJ4819】[Sdoi2017]新生舞会 01分数规划+费用流
- [BZOJ 4819] [Sdoi2017]新生舞会 二分+网络流
- [sdoi2017][bzoj4819] D2T1 新生舞会
- bzoj 4819: [Sdoi2017]新生舞会 二分答案+费用流
- [BZOJ]4819: [Sdoi2017]新生舞会 01分数规划+费用流
- BZOJ4819: [Sdoi2017]新生舞会(01分数规划)
- bzoj4819 [Sdoi2017]新生舞会 01分数规划+二分图最优匹配
- 【BZOJ 4819】 4819: [Sdoi2017]新生舞会 (0-1分数规划、二分+KM)
- bzoj 4819: [Sdoi2017]新生舞会 01分数规划 二分图最优匹配
- BZOJ 4819: [Sdoi2017]新生舞会 01分数规划 二分图最大权匹配(KM算法)/费用流
- BZOJ 4819: [Sdoi2017]新生舞会
- bzoj4819 [Sdoi2017]新生舞会 分数规划(实数二分)+网络流检验