题目描述:
给你一个无向图,问你最少删掉几个点,使这个图成不连通。
解题报告:
概念
(1)一个具有 N 个顶点的图,在去掉任意 k-1 个顶点后 (1<=K<=N) 所得的子图仍连通,
而去掉 K 个顶点后的图不连通则称 G 是连通的, K 称作图 G 的点连通度,记作 K(G)
(2)相应地如果至少去掉 K 条边使这个图不连通,则 K 成为图的边连通度
边连通度:
为每条边赋权值为1,然后求确定一点作为源点,枚举此点外的每个点作为汇点求最大流。
也可以用stoer_wagner算法求得无向图的最小割
点连通度:
求一个给定的无向图的点连通度,可以转换为求边连通度,怎么转换就如下所示:
将点连通度转化为边连通度时怎么建图呢:
1 .构造一个网络 N
若 G 为无向图:
(1) 原 G 图中的每个顶点 v 变成 N 网中的两个顶点 v' 和 v" ,顶点 v' 至 v" 有一条弧(有向边)连接,弧容量为 1;
(2) 原 G 图中的每条边 e = uv ,在 N 网中有两条弧 e’= u"v',e"=v"u' 与之对应, e' 弧容量为 ∞ , e" 弧容量为 ∞
(3)A” 为源顶点, B' 为汇顶点
注意:弧是有向边
若 G 为有向图:
(1) 原 G 图中的每个顶点变成 N 网中的两个顶点 v’ 和 v” ,顶点 v' 至 v” 有一条弧连接,弧容量为 1
(2) 原 G 图中的每条弧 e = uv 变成一条有向轨 u'u"v'v" ,其中轨上的弧 u"v' 的容量为 ∞;
(3)A” 为源顶点, B' 为汇顶点
2 .指定一个源点 A" ,枚举汇点B',求 A" 到 B' 的最大流 F
讲解转自http://blog.sina.com.cn/s/blog_64675f540100l6u3.html
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 2390 | Accepted: 1079 |
Description
Input
Output
Sample Input
0 0 1 0 3 3 (0,1) (0,2) (1,2) 2 0 5 7 (0,1) (0,2) (1,3) (1,2) (1,4) (2,3) (3,4)
Sample Output
0 1 3 0 2
Hint
#include
#include
#include
using namespace std;
#define maxM 10010
#define maxN 110
#define inf 1000000000
#define cc(m,v) memset(m,v,sizeof(m))
struct node {
int u, v, f, next;
} edge[maxM];
int head[maxN], p, lev[maxN], cur[maxN];
int que[maxM], val[maxN], adj[maxM][2];
void init1() {
p = 0, cc(head, -1), cc(val, 0);
}
bool bfs(int s, int t) {
int u, v, qin = 0, qout = 0, i;
cc(lev, 0);
lev[s] = 1, que[qin++] = s;
while (qout != qin) {
u = que[qout++];
for (i = head[u]; i != -1; i = edge[i].next)
if (edge[i].f > 0 && lev[v = edge[i].v] == 0) {
lev[v] = lev[u] + 1, que[qin++] = v;
if (v == t) return 1;
}
}
return lev[t];
}
int dinic(int s, int t) {
int qin, i, k, u, f;
int flow = 0;
while (bfs(s, t)) {
memcpy(cur, head, sizeof (head));
u = s, qin = 0;
while (1) {
if (u == t) {
for (k = 0, f = inf; k < qin; k++)
if (edge[que[k]].f < f)
f = edge[que[i = k]].f;
for (k = 0; k < qin; k++)
edge[que[k]].f -= f, edge[que[k]^1].f += f;
flow += f, u = edge[que[qin = i]].u;
}
for (i = cur[u]; cur[u] != -1; i = cur[u] = edge[cur[u]].next)
if (edge[i].f > 0 && lev[u] + 1 == lev[edge[i].v]) break;
if (cur[u] != -1) {
que[qin++] = cur[u], u = edge[cur[u]].v;
} else {
if (qin == 0) break;
lev[u] = -1, u = edge[que[--qin]].u;
}
}
}
return flow;
}
void addedge(int u, int v, int f) {
edge[p].u = u, edge[p].v = v, edge[p].f = f, edge[p].next = head[u], head[u] = p++;
edge[p].u = v, edge[p].v = u, edge[p].f = 0, edge[p].next = head[v], head[v] = p++;
}
int main() {
int i, j, n, m, k, ans;
while (scanf("%d%d", &n, &m) != -1) {
if (n == 0) { printf("0\n"); continue; }
if (n == 1) { printf("1\n"); continue; }
if (m == 0) { printf("0\n"); continue; }
for (i = 0; i < m; i++) {
while (getchar() != '(');
scanf("%d,%d)", &adj[i][0], &adj[i][1]);
}
ans = inf;
for (i = n; i < 2 * n; i++)
for (j = i - n + 1; j < n; j++) {
init1();
for (k = 0; k < n; k++) addedge(k, k + n, 1);
for (k = 0; k < m; k++)
addedge(adj[k][0] + n, adj[k][1], inf), addedge(adj[k][1] + n, adj[k][0], inf);
int tmp = dinic(i, j);
if (tmp < ans) ans = tmp;
}
if (ans >= inf) ans = n;
printf("%d\n", ans);
}
return 0;
}