1. 程式人生 > >【網絡流基礎模板】

【網絡流基礎模板】

oid 最大 建立 sizeof front 最大匹配 queue ext style

//網絡流dinic

//最大流=最小割

//基本建模
//建源匯,向每個點分別連所限制的邊權,題目所給的邊連inf 
int cnt=1;
inline void insert(int u,int v,int w)
{
    e[++cnt].to=v;
    e[cnt].next=head[u];
    head[u]=cnt;
    e[cnt].f=w;
}
inline void insert(int u,int v,int w)
{
    insert1(u,v,w);
    insert1(v,w,0);
}
inline int dfs(int now,int f)
{
    
if(now==t) return f; for(int i=head[now];i && f;i=e[i].next) { if(e[i].f && dep[e[i].to]==dep[now]+1) { int d=dfs(e[i].to,min(e[i].f,f)); f-=d;ret+=d;e[i].f-=d;e[i^1].f+=d; } } if(!ret) dep[now]=-1; return ret; } inline
bool bfs() { memset(dep,0,sizeof(dep)); q.push(s),dep[s]=1; queue<int> q; while(!q.empty()) { int now=q.front();q.pop(); for(int i=head[now];i;i=e[i].next) if(e[i].f && !dep[e[i].to]) dep[e[i].to]=dep[now]+1,q.push(e[i].to); }
return dep[t]; } inline int dinic() { int ret=0; while(bfs()) ret+=dfs(s,1e9+7); return ret; } //二分圖 //建立超級源匯,連邊權為1,最大流 //最大匹配=最大流 //最大匹配=最小頂點覆蓋 //最大點獨立集=最小邊覆蓋 //最大匹配+最小邊覆蓋=最大點獨立集+最小頂點覆蓋=|V| //最大權閉合子圖 //正點權和-最小割 //二分圖點權最大點獨立集 //點權和-最小割 //點限制的網絡流 //拆點x0為x1->x2邊權為x0的點限制 //費用流 inline int dfs(int now,int f) { if(now==t) { ans+=f*dis[t]; return f; } mark[now]=1; int ret=0; for(int i=head[now];i && f;i=e[i].next) { if(e[i].f && dis[now]+e[i].cost==dis[e[i].to] && !mark[e[i].to]) { int d=dfs(e[i].to,min(f,e[i].f)); e[i].f-=d; e[i^1].f+=d; ret+=d; f-=d; } } return ret; } inline bool spfa() { for(int i=0;i<=n+1;i++) dis[i]=inf; memset(vis,0,sizeof(vis)); memset(mark,0,sizeof(mark)); q.push(s);vis[s]=1;dis[s]=0; while(!q.empty()) { int now=q.front();q.pop();vis[now]=0; for(int i=head[now];i;i=e[i].next) { if(e[i].f && dis[now]+e[i].cost<dis[e[i].to]) { dis[e[i].to]=dis[now]+e[i].cost; if(!vis[e[i].to]) { q.push(e[i].to); vis[e[i].to]=1; } } } } return dis[t]<inf; } inline void insert(int u,int v,int f,int w) { insert1(u,v,f,w); insert1(v,u,0,-w); } inline int dinic() { ans=0; while(spfa()) dfs(s,inf); return ans; } //建圖才是最難滴

【網絡流基礎模板】