zoukankan      html  css  js  c++  java
  • 【SDOI2011】保密

    题面

    https://www.luogu.org/problem/P2494

    题解

    #include<cstdio>
    #include<cstring>
    #include<iostream>
    #include<vector>
    #include<queue>
    #include<cstdlib>
    #define N 705
    #define M 100050
    #define N1M1 42000
    #define ri register int
    #define INF 1000000007.666
    
    using namespace std;
    
    int n,m,m1,n1,cnt;
    int to[M<<1],t[M<<1],s[M<<1];
    vector<int> ed[N];
    vector<int> dap[N];
    double dis[N];
    
    double min(double a,double b) {
      if(a<b)return a;else return b;
    }
    
    void add_edge(int ca,int cb,int ct,int cs) {
      ed[ca].push_back(++cnt);
      to[cnt]=cb; t[cnt]=ct; s[cnt]=cs;
    }
    
    struct initshen {
      double nt[M<<1];
      double f[N];
    
      double dp(int x) {
        if (f[x]<=INF-1) return f[x];
        f[x]=INF-2;
        for (ri i=0;i<ed[x].size();i++) {
          int e=ed[x][i];
          if (e%2==0) continue;
          if (dp(to[e])+nt[e]<f[x]) f[x]=dp(to[e])+nt[e];
        }
        return f[x];
      }
      void solve(vector<int> cur,double lb,double rb) {
        double mid=(lb+rb)/2;
        if (rb-lb<1e-3) {
          for (ri i=0,l=cur.size();i<l;i++) dis[cur[i]]=mid;
          return;
        }
        for (ri i=1;i<=n;i++) f[i]=INF;
        f[n]=0;
        for (ri i=1;i<=cnt;i+=2) nt[i]=t[i]-mid*s[i];
        vector<int> curL,curR;
        for (ri i=0,l=cur.size();i<l;i++) if (dp(cur[i])>=0) curR.push_back(cur[i]); else curL.push_back(cur[i]);
        if (curL.size()) solve(curL,lb,mid);
        if (curR.size()) solve(curR,mid,rb);
      }
      void work() {
        vector<int> cur;
        for (ri i=1;i<=n1;i++) cur.push_back(i);
        solve(cur,0.0,11.0);
        return;
      }
    } wym;
    
    struct DIN {
      #define S 0
      #define T n1+m1+1
      vector<int> ed[N1M1];
      int d[N1M1],cur[N1M1];
      vector<double> w;
      vector<int> to;
    
      void add_edge(int a,int b,double ww) {
        w.push_back(ww);
        to.push_back(b);
        ed[a].push_back(to.size()-1);
        return;
      }
      
      void makeGraph() {
        for (ri i=1;i<=n1;i++) {
          if (i%2==1) {
            add_edge(0,i,dis[i]);
            add_edge(i,0,0);
          }
          else {
            add_edge(i,T,dis[i]);
            add_edge(T,i,0);
          }
        }
        for (ri i=1;i<=n1;i++) {
          if (i%2==1) {
            for (ri j=0,l=dap[i].size();j<l;j++) {
              int y=dap[i][j];
              add_edge(i,n1+y,INF);
               add_edge(n1+y,i,0);
            }
          }
          else {
            for (ri j=0,l=dap[i].size();j<l;j++) {
              int y=dap[i][j];
              add_edge(n1+y,i,INF);
               add_edge(i,n1+y,0);
            }
          }
        }
      }
      
      bool bfs() {
        memset(d,0x3f,sizeof(d));
        d[0]=1;
        queue<int> q;
        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 (d[to[e]]>d[x]+1 && w[e]-1e-5>0) {
              d[to[e]]=d[x]+1;
              q.push(to[e]);
            }
          }
        }
        return d[T]<N1M1;
      }
      
      double dfs(int x,double limit) {
        if (x==T) return limit;
        double tot=0;
        for (ri &i=cur[x];i<ed[x].size();i++) {
          int e=ed[x][i];
          if (d[x]+1==d[to[e]] && w[e]-1e-5>0) {
            double f=dfs(to[e],min(limit,w[e]));
            if (f-1e-5<=0) continue;
            w[e]-=f; w[1^e]+=f;
            tot+=f; limit-=f;
            if (limit-1e-5<=0) return tot;
          }
        }
        return tot;
      }
      
      double dinic() {
        double ret=0;
        while (bfs()) {
          memset(cur,0,sizeof(cur));
          ret+=dfs(S,INF);
        }
        return ret;
      }
      
      void work() {
        makeGraph();
        double ans=dinic();
        if (ans<100) printf("%.1lf
    ",ans); else puts("-1");
      }
    } wls;
    
    int main(){
      scanf("%d %d",&n,&m);
      int ca,cb,ct,cs,u,v;
      cnt=-1;
      for (ri i=1;i<=m;i++) {
        scanf("%d %d %d %d",&ca,&cb,&ct,&cs);
        add_edge(ca,cb,ct,cs);
        add_edge(cb,ca,ct,cs);
      }
      scanf("%d %d",&m1,&n1);
      for (ri i=1;i<=m1;i++) {
        scanf("%d %d",&u,&v);
        dap[u].push_back(i);
        dap[v].push_back(i);
      }
      wym.work();
      wls.work();
    }
  • 相关阅读:
    php基础设计模式(注册树模式、工厂模式、单列模式)
    微信公众平台实现获取用户OpenID的方法
    如何成为一名优秀的工程师(语义篇)
    操作系统死锁原因及必要条件
    Word中怎样删除分节符而不影响前节页面设置
    当代码变更遇上精准测试的总结
    Windows网络命令
    linux shell编程
    Oracle远程登录命令
    数据库别名AS区别
  • 原文地址:https://www.cnblogs.com/shxnb666/p/11278481.html
Copyright © 2011-2022 走看看