业余acmer笔记·四月第四周补题

动物森友会

原题地址
在这里插入图片描述
在这里插入图片描述
代码:
这个完全属于套路题~~(喷血)~~
网络流长这样,二分求最小天数。求最大流满足c[1]+c[2]+…c[n]就可以了
参考博客

在这里插入图片描述
代码来自参考博客

const int N=2e3+10,M=7*N,INF=1e9+10;
 
int n,m,S,T,vc;
 
//以下是网络流模板
struct Edge{
    int to,nxt,w;
}e[M<<1];
int head[N],ecnt;
void AddEdge(int u,int v,int w) {
    e[ecnt]=(Edge){v,head[u],w};
    head[u]=ecnt++;
}
void Link(int u,int v,int w){ AddEdge(u,v,w),AddEdge(v,u,0); }
#define erep(u,i) for(int i=head[u];~i;i=e[i].nxt)
 
int dis[N];
int Bfs(){
    static queue <int> que;
    rep(i,1,vc) dis[i]=INF;
    que.push(S),dis[S]=0;
    while(!que.empty()) {
        int u=que.front(); que.pop();
        erep(u,i) {
            int v=e[i].to,w=e[i].w;
            if(!w || dis[v]<=dis[u]+1) continue;
            dis[v]=dis[u]+1,que.push(v);
        }
    }
    return dis[T]<INF;
}
 
int Dfs(int u,int flowin) {
    if(u==T) return flowin;
    int flowout=0;
    erep(u,i) {
        int v=e[i].to,w=e[i].w;
        if(dis[v]!=dis[u]+1 || !w) continue;
        int t=Dfs(v,min(flowin-flowout,w));
        flowout+=t,e[i].w-=t,e[i^1].w+=t;
        if(flowin==flowout) break;
    }
    if(!flowout) dis[u]=0;
    return flowout;
}
 
int Dinic(){
    int ans=0;
    while(Bfs()) ans+=Dfs(S,INF);
    return ans;
}
 
int a[N][8],c[N],sum;
 
int Check(int mid) {
    if(m*mid<sum) return 0;
    rep(i,1,n+10) head[i]=-1; ecnt=vc=0;
    S=++vc,T=++vc;
    rep(i,1,7) Link(S,++vc,(mid/7+(mid%7>=i))*m);
    rep(i,1,n) {
        vc++;
        Link(vc,T,c[i]);
        rep(j,1,7) if(a[i][j]) Link(j+2,vc,INF);
    }
    return Dinic()==sum;
}
 
 
int main(){
    n=rd(),m=rd();
    rep(i,1,n) {
        c[i]=rd(),sum+=c[i];
        rep(j,1,rd()) a[i][rd()]=1;
    }
    // 二分答案,注意上界设定,防止边权爆int
    int l=0,r=1e9/m,res;
    while(l<=r) {
        int mid=(l+r)>>1;
        if(Check(mid)) r=mid-1,res=mid;
        else l=mid+1;
    }
    printf("%d\n",res);
}

C. Helga Hufflepuff’s Cup

原题地址
在这里插入图片描述
在这里插入图片描述
代码:
三维dp,一开始真没想出来
参考博客
代码来自参考博客
在这里插入图片描述

#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define maxn 100005
#define il inline
#define mod 1000000007
vector<int> g[maxn];
ll dp[maxn][3][15];
int n,num;
ll m,k;
void dfs(int x,int fa)
{
    dp[x][0][0]=k-1;
    dp[x][2][0]=m-k;
    dp[x][1][1]=1;
    for(auto i:g[x])
    {
         if(i!=fa)
         {
             dfs(i,x);//先dfs子树
             ll tmp[15][3]={0};
             for (int j = 0; j <=num ; ++j)//希望加上子树后含有j个k点
             {
                 for (int l = 0; l <=j ; ++l)//子树中含有l个k点
                 {
                     tmp[j][0]+=(dp[i][0][l]+dp[i][1][l]+dp[i][2][l])*dp[x][0][j-l];
                     tmp[j][0]%=mod;
                     tmp[j][1]+=dp[i][0][l]*dp[x][1][j-l];
                     tmp[j][1]%=mod;
                     tmp[j][2]+=(dp[i][2][l]+dp[i][0][l])*dp[x][2][j-l];
                     tmp[j][2]%=mod;
                 }
             }
             for (int j = 0; j <=num ; ++j) 
             {
                 dp[x][0][j]=tmp[j][0];
                 dp[x][1][j]=tmp[j][1];
                 dp[x][2][j]=tmp[j][2];
             }
         }
    }
}
int main() {
    int x;
    cin>>n>>m;
    for (int i = 0; i <n-1 ; ++i) {
        int u,v;
        cin>>u>>v;
        g[v].push_back(u);
        g[u].push_back(v);
    }
    cin>>k>>x;
    num=x;
    dfs(1,0);
    ll ans=0;
    for (int i = 0; i <=x ; ++i) {
        ans+=dp[1][2][i]+dp[1][0][i]+dp[1][1][i];
        ans%=mod;
    }
    cout<<ans%mod;
    return 0;
}

我们不生产博客,我们只是博客的搬运工

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值