先献上自己整理的模板:
dinic算法板子:
#include <bits/stdc++.h>
using namespace std;
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define ll long long
const int N=2e3+50;
const ll inf=0x3f3f3f3f3f3f3f3f;
struct node{
    int v;ll w;
    int ne;
}e[N*N];
int n,cnt=0;
ll m;
int head[N];
ll num[N],sum;
int dep[N],a[N][20];
void add(int u,int v,int f)
{
    e[cnt]={v,f,head[u]};
    head[u]=cnt++;
    e[cnt]={u,0,head[v]};
    head[v]=cnt++;
}
bool bfs(int s,int ed)
{
    memset(dep,-1,sizeof(dep));
    dep[s]=1;
    queue<int>que;que.push(s);
    while(que.size()){
        int u=que.front();que.pop();
        if(u==ed) break;
        for(int i=head[u];i!=-1;i=e[i].ne){
            int v=e[i].v;
            if(dep[v]!=-1||e[i].w==0) continue;
            dep[v]=dep[u]+1;
            que.push(v);
        }
    }
    return dep[ed]!=-1;
}
ll dfs(int u,int ed,ll flow)
{
    ll res=flow;
    if(u==ed) return flow;
    for(int i=head[u];i!=-1;i=e[i].ne){
        int v=e[i].v;
        if(dep[v]!=dep[u]+1||!e[i].w) continue;
        ll d=dfs(v,ed,min(res,e[i].w));
        e[i].w-=d;///步骤4增广路中所有减去d,
        e[i^1].w+=d;///反向边加上d
        res-=d;
        if(res==0) break;
    }
    if(flow==res) dep[u]=-1;///这句话可能是流不下去了
    return flow-res;///真正有用的流
}
ll dinic(int st,int ed)
{
    ll ans=0;
    ll d;
    while(bfs(st,ed)){///第二步构造残留图
        while(d=dfs(st,ed,inf))///第三步找到一条增广路,
            ans+=d;///只需要一次dfs过程实现多次增广路
    }
    return ans;
}
int valid(ll mid)
{
    if(mid*m<sum) return 0;
    int v;
    memset(head,-1,sizeof(head));
    cnt=0,v=0;
    int s=++v,t=++v;
    rep(i,1,7) add(s,++v,1ll*(mid/7+(mid%7>=i))*m);
    rep(i,1,n)
    {
        ++v;add(v,t,num[i]);
        for(int j=1;j<=7;++j) if(a[i][j]) add(j+2,v,inf);
    }
    //puts("****");
    //printf("s:%d t:%d\n",s,t);
    ll res=dinic(s,t);
    return res==sum;
}
int main()
{
    scanf("%d%lld",&n,&m);
    for(int i=1;i<=n;++i){
        scanf("%lld",&num[i]);sum+=num[i];
        int t;scanf("%d",&t);
        while(t--){
            int x;scanf("%d",&x);a[i][x]=1;
        }
    }
    ll l=0,r=1e9/m,ans;
    while(l<=r){
        ll mid=l+r>>1;
        if(valid(mid)) r=mid-1,ans=mid;
        else l=mid+1;
    }
    printf("%lld\n",ans);
    return 0;
}定理:一个图的最小割等价于这个图的最大流
最小割:去掉尽量少的边权,使得图不连通
有的题可能会问你 给你一张图去掉最少的边干嘛干嘛的。。
初步了解了dinic算法和其核心思想,但是代码还是需要模板,短时间内可当黑盒子算法用,以后再慢慢考虑脱板打代码。










