poj 1966(无向图的点连通度。。。。。最大流处理。。。)

题目描述:

给你一个无向图,问你最少删掉几个点,使这个图成不连通。

解题报告:

概念

(1)一个具有 个顶点的图,在去掉任意 k-1 个顶点后 (1<=K<=N) 所得的子图仍连通,

  而去掉 个顶点后的图不连通则称 是连通的, 称作图 的点连通度,记作 K(G)

(2)相应地如果至少去掉 条边使这个图不连通,则 成为图的边连通度

边连通度:

  为每条边赋权值为1,然后求确定一点作为源点,枚举此点外的每个点作为汇点求最大流。

  也可以用stoer_wagner算法求得无向图的最小割

点连通度:

  求一个给定的无向图的点连通度,可以转换为求边连通度,怎么转换就如下所示:

将点连通度转化为边连通度时怎么建图呢:

.构造一个网络 N

若 为无向图:

    (1) 原 图中的每个顶点 变成 网中的两个顶点 v' 和 v" ,顶点 v' 至 v" 有一条弧(有向边)连接,弧容量为 1;

    (2) 原 图中的每条边  = uv ,在 网中有两条弧 e= u"v',e"=v"u' 与之对应, e' 弧容量为 ∞ ,  e" 弧容量为 ∞

    (3)A” 为源顶点, B' 为汇顶点

     注意:弧是有向边

若 为有向图:

    (1) 原 图中的每个顶点变成 网中的两个顶点 v’ 和 v” ,顶点 v' 至 v” 有一条弧连接,弧容量为 1

    (2) 原 图中的每条弧  = uv 变成一条有向轨 u'u"v'v" ,其中轨上的弧 u"v' 的容量为 ∞;

    (3)A” 为源顶点, B' 为汇顶点 

.指定一个源点 A" ,枚举汇点B',求 A" 到 B' 的最大流 

 讲解转自http://blog.sina.com.cn/s/blog_64675f540100l6u3.html 


Cable TV Network
Time Limit: 1000MS   Memory Limit: 30000K
Total Submissions: 2390   Accepted: 1079

Description

The interconnection of the relays in a cable TV network is bi-directional. The network is connected if there is at least one interconnection path between each pair of relays present in the network. Otherwise the network is disconnected. An empty network or a network with a single relay is considered connected. The safety factor f of a network with n relays is:
1. n, if the net remains connected regardless the number of relays removed from the net.
2. The minimal number of relays that disconnect the network when removed.

For example, consider the nets from figure 1, where the circles mark the relays and the solid lines correspond to interconnection cables. The network (a) is connected regardless the number of relays that are removed and, according to rule (1), f=n=3. The network (b) is disconnected when 0 relays are removed, hence f=0 by rule (2). The network (c) is disconnected when the relays 1 and 2 or 1 and 3 are removed. The safety factor is 2.

Input

Write a program that reads several data sets from the standard input and computes the safety factor for the cable networks encoded by the data sets. Each data set starts with two integers: 0<=n<=50,the number of relays in the net, and m, the number of cables in the net. Follow m data pairs (u,v), u < v, where u and v are relay identifiers (integers in the range 0..n-1). The pair (u,v) designates the cable that interconnects the relays u and v. The pairs may occur in any order.Except the (u,v) pairs, which do not contain white spaces, white spaces can occur freely in input. Input data terminate with an end of file and are correct.

Output

For each data set, the program prints on the standard output, from the beginning of a line, the safety factor of the encoded net.

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

The first data set encodes an empty network, the second data set corresponds to a network with a single relay, and the following three data sets encode the nets shown in figure 1.

#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;
}



你可能感兴趣的:(网络流)