• 【SDOI2015】星际战争


    题面

    https://www.luogu.org/problemnew/show/P3324

    题解

    水题。

    二分答案+最大流判可行。

    • 注意最大流解决伤血模型的运用。
    // luogu-judger-enable-o2
    #include<cstdio>
    #include<iostream>
    #include<cstring>
    #include<vector>
    #include<queue>
    #define ri register int
    #define N 505
    #define INF 1000000007
    #define T (n+m+1)
    #define eps 1e-5
    
    using namespace std;
    
    int n,m;
    vector<int> to,ed[N];
    vector<double> w;
    int cur[N],d[N];
    double sum;
    int g[N][N],a[N],b[N];
    
    inline int read() {
      int f=0,ret=0; char ch=getchar();
        while (ch<'0' || ch>'9') f|=(ch=='-'),ch=getchar();
        while (ch>='0'&&ch<='9') ret*=10,ret+=(ch-'0'),ch=getchar();
        return f?-ret:ret;
    }
    
    void add_edge(int u,int v,double w1,double w2) {
      to.push_back(v); w.push_back(w1); ed[u].push_back(to.size()-1);
      to.push_back(u); w.push_back(w2); ed[v].push_back(to.size()-1);
    }
    
    bool bfs() {
      queue<int> q;
      memset(d,0x3f,sizeof(d));
      d[0]=0; q.push(0);
      while (!q.empty()) {
        int x=q.front(); q.pop();
        for (ri i=0,l=ed[x].size();i<l;i++) {
          int e=ed[x][i];
          if (w[e]>eps && d[x]+1<d[to[e]]) {
            d[to[e]]=d[x]+1;
            q.push(to[e]);
          }
        }
      }
      return d[T]<=1000000;
    }
    
    double dfs(int x,double limit) {
      if (x==T || !limit) return limit;
      double tot=0;
      for (ri &i=cur[x];i<ed[x].size();i++) {
        int e=ed[x][i];
        if (d[to[e]]==d[x]+1 && w[e]>eps) {
          double f=dfs(to[e],min(limit,w[e]));
          if (f<eps) continue;
          w[e]-=f; w[1^e]+=f; 
          tot+=f; limit-=f;
          if (limit<eps) return tot;
        }
      }
      return tot;
    }
    
    double dinic() {
      double ret=0;
      while (bfs()) {
        memset(cur,0,sizeof(cur));
        ret+=dfs(0,INF);
      }
      return ret;
    }
    
    bool check(double t) {
      w.clear(); to.clear();
      for (ri i=0;i<=n+m+1;i++) ed[i].clear();
      for (ri i=1;i<=m;i++) add_edge(0,i,t*b[i],0);
      for (ri i=1;i<=n;i++) add_edge(m+i,T,a[i],0);
      for (ri i=1;i<=m;i++)
         for (ri j=1;j<=n;j++) if (g[i][j]) add_edge(i,m+j,INF,0);
      if (dinic()+eps>sum) return 1; else return 0;
    }
    
    int main() {
      n=read(); m=read();
      for (ri i=1;i<=n;i++) a[i]=read();
      sum=0.0;
      for (ri i=1;i<=n;i++) sum+=a[i];
      for (ri i=1;i<=m;i++) b[i]=read();
      for (ri i=1;i<=m;i++)
         for (ri j=1;j<=n;j++) g[i][j]=read();
      double lb=0,rb=10007; double ans=-1;
      while (rb-lb>1e-4) {
        double mid=(lb+rb)/2;
         if (check(mid)) ans=mid,rb=mid; else lb=mid;
      }
      printf("%.4lf",ans);
      return 0;
    }
  • 相关阅读:
    2006年百度之星程序设计大赛试题初赛题目题4剪刀石头布
    2006年百度之星程序设计大赛试题初赛题目题5座位调整
    Linux2.6用户空间堆栈区的分配与回收
    Linux2.6物理内存管理
    2006年百度之星程序设计大赛试题初赛题目题6百度语言翻译机
    带权的二分匹配
    二分图带权匹配KuhnMunkres算法(有修改)
    Linux2.6虚拟内存管理
    Linux2.6为数据结构分配内存slab
    2012225面试题目
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11104957.html
Copyright © 2020-2023  润新知