POJ 1966 Cable TV Network (用最大流求最小割点数量)
来源:互联网 发布:层次分析法判断矩阵 编辑:程序博客网 时间:2024/05/16 08:58
这道题,要注意,写网络流的时候,最好最好不要破坏原来的矩阵,尤其是需要多次求一个图的最大流的时候。
这道题,是求一个图的最小割点数。开始以为有专门的算法可以用呢,不过没有找到,然后想拆点求最小割,但是不知道无向图应该怎么建,如果正常拆点的话,拆出来的图还是一个有向图,SW只是解决无向图的情况,很纠结!要是哪位大牛路过知道有更好的算法的话,跪求指点!
这道题的做法就是,拆点,将每个点拆为入点和出点,入点和出点之间流量为1,其他点之间流量为INF,同时要注意的是,源点和汇点是不能被删掉的,所以,当你要决定哪一个点是源点或汇点的时候,记得把相应的出点和入点之间的流量改INF,因为能被删掉的一定是流量为1的边,也就是其他的点;还要注意的是,不要枚举相连的点,也就是在没有拆点之前,是相邻的点,因为在拆点之后,确定了源点和汇点,并更改了出点和入点之间的流量,那么最大流必然大于等于INF,而且相邻的点求割点,典型的没有意义,就像是一共两个点,两个点之间有一条边,删除最少的使得这个图不两通,根据题意,就是最少删除两个,把这种情况放到一个图里面,不也一样吗!所以枚举不相邻的点作为源点和汇点,一次求最大流,找出最小的最大流,就是答案了!
这里还要注意对特殊数据的特殊处理:
有一个点和0条边的,输出1;
有0个点和0条边的,输出0;
图本身就是不连通的,输出0;
以上这三情况,就不用算了。
最后,如果最小的最大流为INF,那么说明,这个图要想不连通,就删除所有点,输出n。
代码:(这里用SAP算法,但是经过实践,另外的那个算法(我不记得名字了,就是bfs找增广路)也能过)
#include <cstdio>#include <cstring>#include <algorithm>#include <iostream>#include <cctype>#include <queue>using namespace std;const int INF = 0x3fffffff;const int N = 110;int n, m, u, v, flag, g[N][N], f[N];char s[10], ch;int gap[N], dis[N], pre[N], cur[N];int a[N], flow[N][N];/*int Maxflow( int S, int E, int nodenum ){ queue<int> q; int maxflow = 0; memset(flow, 0, sizeof(flow)); while ( 1 ) { memset(a, 0, sizeof(a)); a[S] = INF; q.push(S); while ( !q.empty() ) { int u = q.front(); q.pop(); for ( int v = 0; v < nodenum; ++v ) if ( !a[v] && g[u][v] > flow[u][v] ) { pre[v] = u; q.push(v); a[v] = min( a[u], g[u][v] - flow[u][v] ); } } if ( a[E] == 0 ) break; for ( int u = E; u != S; u = pre[u] ) { flow[pre[u]][u] += a[E]; flow[u][pre[u]] -= a[E]; } maxflow += a[E]; } return maxflow;}*/int Maxflow( int S, int E, int nodenum ){ memset( cur, 0, sizeof(cur)); memset( dis, 0, sizeof(dis)); memset( gap, 0, sizeof(gap)); memset( flow,0, sizeof(flow)); int u = pre[S] = S, aug = -1, maxflow = 0; gap[0] = nodenum; while ( dis[S] < nodenum ) {loop: for ( int v = cur[u]; v < nodenum; v++ ) if ( g[u][v]-flow[u][v] && dis[u]==dis[v]+1 ){ if ( aug == -1 || aug > g[u][v]-flow[u][v] ) aug = g[u][v]-flow[u][v]; pre[v] = u; u = cur[u] = v; if ( v == E ) { maxflow += aug; for ( u = pre[u]; v != S; v = u, u = pre[u] ){ flow[u][v] += aug; flow[v][u] -= aug; } aug = -1; } goto loop; } int mindis=nodenum - 1; for ( int v = 0; v < nodenum; v++ ) if ( g[u][v]-flow[u][v] && mindis > dis[v] ){ cur[u] = v; mindis = dis[v]; } if ( (--gap[dis[u]]) == 0 ) break; gap[dis[u] = mindis+1] ++; u = pre[u]; } return maxflow;}int find( int x ) { return f[x] == x ? x : (f[x] = find(f[x]));}void init(){ memset( g, 0, sizeof(g)); for ( int i = 0; i < n; ++i ) f[i] = i; while ( m ) { ch = getchar(); if ( ch == ')' ) { m--; g[u][u+n] = g[v][v+n] = 1; g[u+n][v] = g[v+n][u] = INF; int a = find(u); int b = find(v); if ( a!=b ) f[a] = b; } if ( ch == '(' ) u = 0, flag = 1; if ( ch == ',' ) v = 0, flag = 2; if ( isdigit(ch) ) if ( flag == 1 ) u = u * 10 + ( ch - '0' ); else if ( flag == 2 ) v = v * 10 + ( ch -'0' ); }}int main(){ while ( scanf("%d%d", &n, &m) != EOF ) { if ( m == 0 ) { if ( n == 1 ) printf("1\n"); else printf("0\n"); continue; } init(); int is = 0, ans = INF; for ( int i = 0; i < n; ++i ) if ( f[i] == i ) { is++; if ( is > 1 ) break; } if ( is > 1 ) { printf("0\n"); continue; } for ( int i = 0; i < n; ++i ) for ( int j = i + 1; j < n; ++j ) if ( !g[i+n][j] ) { g[i][i+n] = INF; g[j][j+n] = INF; int tmp = Maxflow( i, j+n, 2*n ); //cout << i << ' ' << j << ' ' << tmp << endl; if ( ans > tmp ) ans = tmp; g[i][i+n] = g[j][j+n] = 1; } if ( ans == INF ) ans = n; printf("%d\n", ans); }}
- POJ 1966 Cable TV Network (用最大流求最小割点数量)
- POJ 1966 Cable TV Network 最小割
- 点连通度 边连通度 最大流最小割 最小割点集 最小割边集 & POJ 1966 Cable TV Network
- POJ 1966 Cable TV Network | 最小点割集、最小割
- 1660 - Cable TV Network(最大流最小割)
- vua 1660 Cable TV Network 最大流最小割 求割点
- POJ 1966 - Cable TV Network 暴力枚举+最小点割
- POJ 1966 Cable TV Network 枚举最小割
- POJ 1966--Cable TV Network【最小割 && 枚举终点起点】
- poj 1966 Cable TV Network 无向图最小割
- Cable TV Network- POJ 1966 连通量
- poj 1966 Cable TV Network 顶点连通度-最大流
- poj--1966[Cable TV Network] 拆点+枚举源汇求最小割
- poj 1966 Cable TV Network 【枚举源汇 求解 无向图最小割】
- Tarjan求割点数量:Network
- poj 1966 zoj 2182 Cable TV Network(无向图顶点连通度(sap求最大流))
- POJ 1966--Cable TV Network 【求无向图的点连通度 构造最大流模型 && dinic】
- POJ 1144 Network(割点数量)
- MemCached Cache Java Client封装优化历程
- c语言代码风格格式化工具
- 全排列
- JNI之GetMethodID方法签名
- 程上下文和中断上下文
- POJ 1966 Cable TV Network (用最大流求最小割点数量)
- IT must prepare for Hadoop security issues
- 多线程的基本应用
- 第十一届北京师范大学程序设计竞赛(网络同步赛)+Adidas and adivon
- ubuntu下更新grub2
- 把IE浏览器的背景改成保护视力的颜色
- How hashmap works in java
- nyoj 155 求高精度幂
- jQuery打造动态渐变按钮