最大流与最小割
1、POJ 3713 Transferring Sylla
题意:判断一个无向图是否三连通?
思路:枚举每个点,删去后用Tarjan判断图中是否存在割点,如果存在则该图不满足三连通性。
// #include<bits/stdc++.h> #include <cstdio> #include <iostream> #include <algorithm> #include <cstring> // for memset #include <vector> // vector<int>().swap(v); #define IOS ios_base::sync_with_stdio(0); cin.tie(0) #define lowbit(x) (x&(-x)) using namespace std; typedef long long ll; int del,root; bool cut; int dfn[510], low[510]; vector<int> e[510]; int n,m; int tot; void Tarjan(int u,int p) { if(cut) return; dfn[u]=low[u]= ++tot; int son=0; for(vector<int>::iterator it=e[u].begin();it!=e[u].end();it++) { int v=*it; if(v==p || v==del) continue; if(!dfn[v]) { son++; Tarjan(v,u); low[u]=min(low[u],low[v]); if((u == root && son > 1) || (u != root && low[v] >= dfn[u])) { cut=true; return; } }else{ low[u]=min(low[u],dfn[v]); } } } int main(void) { while (scanf("%d%d", &n, &m) != EOF && n) { for (int i = 0; i < n; ++i) e[i].clear(); for (int i = 0; i < m; ++i) { int u, v; scanf("%d%d", &u, &v); e[u].push_back(v); e[v].push_back(u); } cut = 0; for (int i = 0; i < n; ++i) { del = i; memset(dfn, 0, sizeof(dfn)); tot = 0; root = !i; Tarjan(root, -1); if (cut) break; for (int j = 0; j < n; ++j) { if (j != del && !dfn[j]) { cut = 1; break; } } if (cut) break; } printf("%s\n", cut ? "NO" : "YES"); } return 0; }
2、POJ 2987 Firing
题意:老板决定大裁员,每开除一个人,同时要将其下属一并开除,以及下属的下属... ... 给出开除掉每个人的贡献值和各种从属关系,求最小裁员数及最大贡献值和。
定义一个有向图 G=(V,E) 的闭合图是该有向图的一个点集,且该点集的所有出边都还指向该点集。即闭合图内的任意点的任意后继也一定在闭合图中。
// 最大权闭合图的求解方法是: 1.先构造网络流N,添加源点s,从s到正权值点做一条边,容量为点的权值。 2.添加汇点t,从负权值点到t做一条边,容量为点的权值的绝对值。 3.原来的边的容量统统设为无穷大。 4.求解最小割,最大权=正权值之和-最小割权值 5.残余网络中的点的个数即为裁员个数。
感觉网络流不是很好理解,这个题先放一下
3、POJ 2914 Minimum Cut
题意:求无向图的最小割。
思路:Stoer-Wagner算法
哎这道题还是一头雾水,还是先放一下,滚去复习图论的知识点了 555 菜到无法呼吸