生活随笔
收集整理的這篇文章主要介紹了
洛谷P3386:网络流之二分图匹配,最大流算法
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
二分圖:我的理解是,對圖中的點集,可分為兩個集合U和V,使得兩個集合之間存在通路,且集合內部不存在通路。如上圖。
匹配:兩兩不含公共端點的邊集合M
最大匹配:邊數最多的匹配
完美匹配:最大匹配的匹配數滿足2*M=點的總數
二分圖匹配:二分圖中的匹配
實際上,可將二分圖最大匹配問題看作是最大流問題的特殊情況。
最大流方法解決二分圖匹配:
將原圖中的所有無向邊e改為有向邊,方向從U到V,容量為1.增加原點s和匯點t,從s向所有的頂點u∈U連一條容量為1的邊,從所有的頂點v∈V連一條容量為1的邊。
ff方法解決二分圖匹配(洛谷p3386):
class Main{static int maxn
=1010;static ArrayList
<edge
> G[]=new ArrayList[2*maxn
];static boolean vis
[]=new boolean[2*maxn
];static class edge{int to
,cap
,rev
;public edge(int to
,int cap
,int rev
) {this.to
=to
;this.cap
=cap
;this.rev
=rev
;}}static boolean
dfs(int v
,int t
){if(v
==t
){return true;}vis
[v
]=true;int u
,cap
,rev
;for(int i
=0;i
<G[v
].size();i
++){u
=G[v
].get(i
).to
;cap
=G[v
].get(i
).cap
;rev
=G[v
].get(i
).rev
;if(!vis
[u
]&&cap
>0&&dfs(u
,t
)){G[u
].get(rev
).cap
++;G[v
].get(i
).cap
--;return true;}}return false;}static void add_edge(int v
,int u
){G[v
].add(new edge(u
,1,G[u
].size()));G[u
].add(new edge(v
,0,G[v
].size()-1));}static int
max_flow(int s
,int t
){int res
=0;for(;;){for(int i
=0;i
<2*maxn
;i
++) {vis
[i
]=false;}if(dfs(s
,t
)) {res
++;}else {break;}}return res
;}public static void main(String args
[]){InputReader sc
=new InputReader(System
.in);PrintWriter out
=new PrintWriter(System
.out
);int n
=sc
.nextInt();int m
=sc
.nextInt();int e
=sc
.nextInt();for(int i
=1;i
<=n
+m
+10;i
++) {G[i
]=new ArrayList<>();}int u
,v
;for(int i
=0;i
<e
;i
++) {u
=sc
.nextInt();v
=sc
.nextInt();if(v
<=m
&&u
<=n
) {add_edge(u
, v
+n
);}}int s
=n
+m
+1;int t
=s
+1;G[s
]=new ArrayList<edge
>();G[t
]=new ArrayList<edge
>();for(int i
=1;i
<=n
;i
++) {add_edge(s
, i
);}for(int i
=n
+1;i
<=n
+m
;i
++) {add_edge(i
, t
);}out
.println(max_flow(s
,t
));out
.flush();out
.close();}
}
總結
以上是生活随笔為你收集整理的洛谷P3386:网络流之二分图匹配,最大流算法的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。