[Confidential] SDOI2011

Face questions

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

answer

#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\n",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();
}

 

Guess you like

Origin www.cnblogs.com/shxnb666/p/11278481.html