Dinic求最大流 最小割

2021-09-25 12:30:45 字數 4615 閱讀 8521

o(v^2*e)

建圖時建一條流量為0的反向邊,正向邊每減去流量f,反向邊增加流量f.對於無向圖當做兩條邊。

cap:每條邊最大流量

建圖後:

呼叫dinic():用bfs()為每個節點進行層次編號,在每種層次編號下,用dinic()即dfs找到所有增廣路,加到最大流結果。

theme:給定m條邊,n個點,1為源點,n為匯點,給定每條邊和改變的最大流量,求最大流。

solution:最大流裸題。

#include#include#include#includeusing namespace std;

int const size=300;

int const inf=0x3f3f3f3f;

int dis[size];

int cur[size];

int cnt;//邊總數

int m,n,n;//n為網路流中總點數

int s,t;

struct edge

//為宣告edge陣列而設

edge(int a,int b,int c):u(a),v(b),cap(c){}

}edge[size*size];

vectorve[size];

void creatg()

}bool bfs()}}

return dis[t]0&&dis[e.v]==dis[u]+1)}}

return 0;

}int dinic()

return ans;

}int main()

for(int i=1;i<=n;++i)

ve[f+i+1].push_back(cnt);

edge[cnt++]=edge(f+i+1,f+n+i+1,1);

ve[f+i+n+1].push_back(cnt);

edge[cnt++]=edge(f+i+n+1,f+i+1,0);

while(di--)

}for(int i=1;i<=d;++i)

}

網路流時間複雜度還是挺高的,如果n很大的話可能建圖時就超時了,所以要適當縮點。

theme:n個人,m個房間,給定每個房間能容納的人數與每個人能去哪幾個房間的資訊,問能否安排每個人都進房間?1 <= n <= 100000,1 <= m <= 10

solution:n很大,直接建圖超時,但是m很小,所以可以將能進相同種類的人看做乙個整體用二進位制表示,記錄下人數,最多2^10種,即將n縮小了,再建圖

//建圖部分**:

unordered_mapmp;

unordered_map::iterator it;

void creatg()

x>>=1;}}

for(int i=1;i<=m;++i)

}int main()

mp[x]++;

}int sz=mp.size();

t=m+sz+2;

n=t;

for(int i=1;i<=n;++i)

ve[i].clear();

creatg();

int ans=dinic();

if(ans==n)

puts("yes");

else

puts("no");}}

要建反向邊,反向邊流量為0,費用為-cost

theme:給定n個點,m條邊,每條邊的長度,問從點1到n再從n回到1且除源點與匯點外,其他點只經過一次的最短路徑。1 <= n <= 1000,1 <= m <= 10000 ,路徑

solution:就算沒有點只經過一次,跑最短路刪邊再跑一遍最短路也是不對的。有點的限制,考慮用網路流。又最終求最短路,所以考慮最小費用最大流。要再回去,所以在源點之後與匯點之前各加乙個點,流量為2,費用為0.每個點只能訪問一次,所以定義每條邊的流量為1,費用為0.

//給定乙個無向圖,要從1點到n點再返回1點,每條邊最多走一次,問最短需要走多遠

//題目給出了n個點、m條邊, 邊的容量均為1

//新增乙個源、連線1點、容量為2

//新增乙個匯, n點到匯,容量為2

#include #include #include using namespace std;

typedef int capa_t;

typedef int cost_t;

#define size 1010

int n,m;

//邊struct edge_tedge[size*40];

int ecnt;

//圖edge_t* ver[size];

//建立邊

void mkedge(int a,int b,capa_t capa,cost_t cost)

inline edge_t* neg(edge_t* p)

cost_t d[size];

bool flag[size];

edge_t* pre[size];//邊,通過該陣列可以還原最短路徑

//spfa演算法,使用cost作為權值來衡量最短路徑

void spfa(int s)

} }}//最小費用最大流,s為源,t為匯

int mcmf(int s,int t)

//更新費用

minicost += d[t] * flow;

} return minicost;

}bool read()

edge(int to, int _cap, int _cost, int _rev) :to(to), cap(_cap), cost(_cost), rev(_rev) {}

};int v, h[maxn + 5], dis[maxn + 5], prev[maxn + 5], pree[maxn + 5];

vectorg[maxn + 5];//點

void init(int n)

//建邊與反向邊

void addedge(int from, int to, int cap, int cost)

//mcmf

int min_cost_max_flow(int s, int t, int f, int& flow) }}

if (dis[t] == inf)break;

for (int i = 0; i <= v; ++i)h[i] += dis[i];

int d = f;

for (int v = t; v != s; v = prev[v])d = min(d, g[prev[v]][pree[v]].cap);

f -= d; flow += d; res += d*h[t];

for (int v = t; v != s; v = prev[v])

}return res;

}int a[maxn];

int main()}}

int ans=0;

printf("%d\n",-min_cost_max_flow(ss,tt,inf,ans));

}return 0;

}

設s為源點,t為匯點。

使s連向所有的正權點(非負權點),邊權為點權。

使所有非負權點(負權點)連向t,邊權為點權的絕對值(正)。

若需要選y才能選x,連一條由x到y的邊,邊權是∞。

最大點權和=正權點和-最小割。

theme:有n種物品,價值為v,成本為c,且買物品i可能需要先買m中別的型別物品。求能買到的最大價值物品和。

solution:對於每個物品i,如果v-c>=0則建立一條源點到i,權值為v-c的邊,否則建立一條i到匯點,權值為c-v的邊。最後算出正權點和-最小割,即

#include#include#include#includeusing namespace std;

int const size=300;

int const inf=0x3f3f3f3f;

int dis[size];

int cur[size];

int cnt=1;

int needv;

int n,n;

int s,t;

struct edge

//為宣告edge陣列而設

edge(int a,int b,int c):u(a),v(b),cap(c){}

}edge[size*size];

vectorve[size];

void creatg()

else

while(m--)

}}bool bfs()}}

return dis[t]0&&dis[e.v]==dis[u]+1)}}

return 0;

}int dinic()

return ans;

}int main()

{ cin>>n;

s=0;

t=n+1;

n=n+2;

for(int i=0; i<=n; ++i)

ve[i].clear();

creatg();

int mycost=dinic();

cout<

模板 EK求最大流 dinic求最大流

acm模板 yxc老師的部分總結 基本概念 1.1 流網路,不考慮反向邊 1.2 可行流,不考慮反向邊 1.2.1 兩個條件 容量限制 流量守恆 1.2.2 可行流的流量指從源點流出的流量 流入源點的流量 1.2.3 最大流是指最大可行流 1.3 殘留網路,考慮反向邊,殘留網路的可行流f 原圖的可行...

Dinic演算法求最大流

include using namespace std const int oo 1e9 無窮大 const int maxm 111111 邊的最大數量,為原圖的兩倍 const int maxn 999 點的最大數量 int node,src,dest,edge node節點數,src源點,de...

最大流 最小割

真是不知道該說些什麼呀 感覺這是我見到過的網上敘述最最最詳細的乙個演算法了。可見我才學過幾個演算法qwq 我並不認為我能比網上講的要好 所以 emmm 我就打算解釋一下 不要管這迷一樣的邏輯 先去看看題解hhh 咳咳 等會兒 好了好了 qwq 言歸正傳 這裡的dinic演算法,是對edmonds k...