LOADING

加载过慢请开启缓存,浏览器默认开启

daily 2

2023/5/21 daily

CF 808F

看到最小的level,我们可以选择二分答案,然后建图就是把所有的卡片按照奇偶进行二分图,因为要产生质数只可能是奇数+偶数,所以我们这里把能产生质数的两张卡进行连边,流量就是INF,跑最大流,获得的就是可以丢弃的最大p,那么最小的p就是sum-p了

struct node{
    int p,c,l;
};
struct Dinic
{
  struct Edge
  {
    int from,to,cap,flow;
    Edge(int f,int t,int c,int w):from(f),to(t),cap(c),flow(w){}
  };
  int n,m,s,t;//size of point and line and the start point and end point
  vector<int>d,cur;
  vector<bool>vis;
  vector<Edge>E;
  vector<vector<int>>G;
  const int INF=0x3f3f3f3f;
  Dinic(int n,int m):n(n),m(m)
  {
    d.resize(n+1);
    vis.resize(n+1,false);
    G.resize(n+1);
    cur.resize(n+1);
  }
  void add_edge(int from,int to,int cap)
  {
    E.push_back({from,to,cap,0});
    G[from].push_back(E.size()-1);
    E.push_back({to,from,0,0});
    G[to].push_back(E.size()-1); 
  }
  bool bfs()//get the depth of every point
  {
    fill(vis.begin(),vis.end(),false);
    queue<int>q;
    q.push(s);
    d[s]=0;
    vis[s]=1;
    while(!q.empty())
    {
      int x=q.front();
      q.pop();
      for(int i=0;i<G[x].size();++i)
      {
        auto& e=E[G[x][i]];
        if(!vis[e.to]&&e.cap>e.flow)
        {
          vis[e.to]=1;
          d[e.to]=d[x]+1;
          q.push(e.to);
        }
      }
    }
    return vis[t];
  }
  ll dfs(int x,int a)
  {
    if(x==t||a==0)return a;
    ll res=0,f;
    for(int& i=cur[x];i<G[x].size();++i)
    {
      auto& e=E[G[x][i]];
      if(d[x]+1==d[e.to]&&(f=dfs(e.to,min(a,e.cap-e.flow)))>0)
      {
        e.flow+=f;
        E[G[x][i]^1].flow-=f;
        res+=f;
        a-=f;
        if(a<=0)break;
      }
    }
    return res;
  }
  ll maxflow(int s,int t)
  {
    this->s=s;
    this->t=t;
    ll ans=0;
    while(bfs())
    {
      fill(cur.begin(),cur.end(),0);
      ans+=dfs(s,INF);//INF is the now flow
    }
    return ans;
  }
};
void solve(){
  int n,k;
  cin>>n>>k;
  vector<node>cards(n+1);
  int l=INT_MAX,r=INT_MIN;
  for(int i=1;i<=n;++i){
    cin>>cards[i].p>>cards[i].c>>cards[i].l;
    l=min(l,cards[i].l);
    r=max(r,cards[i].l);
  }
  auto check_prime=[&](int num){
    for(int i=2;i<=sqrt(num);++i){
        if(num%i==0)return 0;
    }
    return 1;
  };
  auto check=[&](int mini_level){
    int S=n+1,T=n+2;
    int maxp_one=-1;
    for(int i=1;i<=n;++i){
        if(cards[i].c==1&&cards[i].l<=mini_level){
            maxp_one=max(maxp_one,cards[i].p);
        }
    }
    ll sum=0;
    bool one_flag=false;
    vector<int>choosed;
    for(int i=1;i<=n;++i){
        if((cards[i].l<=mini_level&&cards[i].c!=1)||(cards[i].c==1&&cards[i].p==maxp_one&&!one_flag)){
            if(cards[i].c==1){
                one_flag=true;
            }
            choosed.push_back(i);
            sum+=cards[i].p;
        }
    }
    Dinic dinic(n+3,0);
    for(int i=0;i<choosed.size();++i){
        if(cards[choosed[i]].c&1){
            dinic.add_edge(S,choosed[i],cards[choosed[i]].p);
        }else{
            dinic.add_edge(choosed[i],T,cards[choosed[i]].p);
        }
        for(int j=i+1;j<choosed.size();++j){
            if(check_prime(cards[choosed[i]].c+cards[choosed[j]].c)){
                if(cards[choosed[i]].c&1)dinic.add_edge(choosed[i],choosed[j],INF);
                else dinic.add_edge(choosed[j],choosed[i],INF);
            }
        }
    }
    auto maxflow=dinic.maxflow(S,T);
    return sum-maxflow>=k;
  };
  int ans=-1;
  while(l<=r){
    int m=(l+r)>>1;
    if(check(m)){
        r=m-1;
        ans=m;
    }else{
        l=m+1;
    }
  }
  cout<<ans<<'\n';
  return;
}

CF 510E

和上面的做法类似,不过这次我们需要保存是质数的两只狐狸,原点向奇数狐狸连线(cap=2),然后奇数狐狸向产生质数的偶数狐狸连线(cap=1),然后偶数狐狸向汇点连线(cap=2),看最大流是不是n,如果是那么就是可分的,然后我们按着奇数->偶数有边,遍历我们的图,把每一桌的狐狸给整进去就可以了。老子的板子好像开始有点问题,调了贼几把久。

struct Dinic
{
  struct Edge
  {
    int from,to;
    ll cap;
    Edge(int f,int t,int c):from(f),to(t),cap(c){}
  };
  int n,m,s,t;//size of point and line and the start point and end point
  vector<int>d,cur;
  vector<bool>vis;
  vector<Edge>E;
  vector<vector<int>>G;
  const int INF=0x3f3f3f3f;
  Dinic(int n,int m):n(n),m(m)
  {
    d.resize(n+1);
    vis.resize(n+1,false);
    G.resize(n+1);
    cur.resize(n+1);
  }
  void add_edge(int from,int to,int cap)
  {
    E.push_back({from,to,cap});
    G[from].push_back(E.size()-1);
    E.push_back({to,from,0});
    G[to].push_back(E.size()-1); 
  }
  bool bfs()//get the depth of every point
  {
    fill(vis.begin(),vis.end(),false);
    queue<int>q;
    q.push(s);
    d[s]=0;
    vis[s]=1;
    while(!q.empty())
    {
      int x=q.front();
      q.pop();
      for(int i=0;i<G[x].size();++i)
      {
        auto& e=E[G[x][i]];
        if(!vis[e.to]&&e.cap)
        {
          vis[e.to]=1;
          d[e.to]=d[x]+1;
          q.push(e.to);
        }
      }
    }
    return vis[t];
  }
  ll dfs(int x,ll a)
  {
    if(x==t||a==0)return a;
    ll res=0,f;
    for(int& i=cur[x];i<G[x].size();++i)
    {
      auto& e=E[G[x][i]];
      if(d[x]+1==d[e.to]&&e.cap)
      {
        int f=dfs(e.to,min(a-res,e.cap));
        e.cap-=f;
        E[G[x][i]^1].cap+=f;
        res+=f;
        if(res==a)break;
      }
    }
    return res;
  }
  ll maxflow(int s,int t)
  {
    this->s=s;
    this->t=t;
    ll ans=0;
    while(bfs())
    {
      fill(cur.begin(),cur.end(),0);
      ans+=dfs(s,INF);//INF is the now flow
    }
    return ans;
  }
};
void solve(){
  int n;
  cin>>n;
  vector<int>f(n+1);
  for(int i=1;i<=n;++i)cin>>f[i];
  auto check_prime=[&](int num){
    for(int i=2;i<=sqrt(num);++i){
        if(num%i==0){
            return 0;
        }
    }
    return 1;
  };
  Dinic dinic(n+3,0);
  int S=0,T=n+1;
  auto check=[&](){
    vector<int>odd,even;
    for(int i=1;i<=n;++i){
        if(f[i]&1){
            odd.push_back(i);
            dinic.add_edge(S,i,2);
        }else{
            even.push_back(i);
            dinic.add_edge(i,T,2);
        }
    }
    for(int i=0;i<odd.size();++i){
        for(int j=0;j<even.size();++j){
            if(check_prime(f[odd[i]]+f[even[j]])){
                dinic.add_edge(odd[i],even[j],1);//odd->even
            }
        }
    }
    auto maxflow=dinic.maxflow(S,T);
    return maxflow==n;
  };
   //first checkout whether it is possible to arrange all foxes
  if(!check()){
    cout<<"Impossible\n";
    return;
  }
  vector<vector<int>>groups;
  //then we use dfs to arrange all foxes
  vector<int>vis(n+1);
  function<void(int)>dfs=[&](int cur){
    groups.back().push_back(cur);
    vis[cur]=1;
    for(int id:dinic.G[cur]){
        auto e=dinic.E[id];
        if(e.to==S||e.to==T||vis[e.to])continue;
        if((e.cap==0&&f[e.from]%2==1)||(dinic.E[id^1].cap==0&&f[e.to]%2==1)){
            dfs(e.to);
        }
    }
  };
  for(int i=1;i<=n;++i){
    if(!vis[i]){
        groups.push_back(vector<int>());
        dfs(i);
    }
  }
  cout<<groups.size()<<'\n';
  for(int i=0;i<groups.size();++i){
    cout<<groups[i].size()<<' ';
    for(int num:groups[i]){
        cout<<num<<' ';
    }
    cout<<'\n';
  }
  return;
}