链接:http://poj.org/problem?id=1966

题意:一个无向图,n个点,m条边,求此图的顶点连通度。

思路:顶点连通度,即最小割点集里的割点数目。一般求无向图顶点连通度的方法是转化为网络流的最小割。

建图:

(1)原图每一个点i拆点,拆为i‘和i’‘,i’到i‘’连一条弧容量为1。

(2)对于原图中存在的边(u, v),连两条弧(u‘, v')和(v'', u'),容量INF。

(3)找一个源点i。这个点不能和其它全部点都相邻否则无法找到最小割,以这个点i''为源点,枚举汇点j'。

图建好了之后求n-1遍最大流。答案最小的那个就是此图的顶点连通度,i'到i''满流的i点组成了最小割点集。

#include<cstring>
#include<string>
#include<fstream>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cctype>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<ctime>
#include<cstdlib>
#include<functional>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
#define MAXN 1010
#define eps 1e-7
#define INF 0x3F3F3F3F //0x7FFFFFFF
#define LLINF 0x7FFFFFFFFFFFFFFF
#define seed 1313131
#define MOD 1000000007
#define ll long long
#define ull unsigned ll
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1 struct node{
int u,v,w,next;
}edge[500000],edge2[500000];
int head[120],dist[120],cur[120],fa[120],num[120],vis[120];
int n,m,k,cnt,nn,src,sink;
void add_edge(int a,int b,int c){
edge2[cnt].u = a;
edge2[cnt].v = b;
edge2[cnt].w = c;
edge2[cnt].next = head[a];
head[a] = cnt++;
}
void bfs()
{
int x,i,j;
queue<int> q;
memset(dist,-1,sizeof(dist));
memset(num,0,sizeof(num));
q.push(sink);
dist[sink] = 0;
num[0] = 1;
while(!q.empty()){
x = q.front();
q.pop();
for(i=head[x];i!=-1;i=edge[i].next){
if(dist[edge[i].v]<0){
dist[edge[i].v] = dist[x] + 1;
num[dist[edge[i].v]]++;
q.push(edge[i].v);
}
}
}
} int augment()
{
int x=sink,a=INF;
while(x!=src){
a = min(a,edge[fa[x]].w);
x = edge[fa[x]].u;
}
x=sink;
while(x!=src){
edge[fa[x]].w -= a;
edge[fa[x]^1].w += a;
x = edge[fa[x]].u;
}
return a;
} int isap()
{
int i,x,ok,minm,flow=0;
bfs();
for(i=0;i<=nn+5;i++) cur[i] = head[i];
x=src;
while(dist[src]<nn){
if(x==sink){
flow += augment();
x = src;
}
ok=0;
for(i=cur[x];i!=-1;i=edge[i].next){
if(edge[i].w && dist[x]==dist[edge[i].v]+1){
ok=1;
fa[edge[i].v] = i;
cur[x] = i;
x = edge[i].v;
break;
}
}
if(!ok){
minm = nn;
for(i=head[x];i!=-1;i=edge[i].next)
if(edge[i].w && dist[edge[i].v]<minm) minm=dist[edge[i].v];
if(--num[dist[x]]==0)break;
num[dist[x]=minm+1]++;
cur[x]=head[x];
if(x!=src) x=edge[fa[x]].u;
}
}
return flow;
}
int main(){
int i,j;
int a,b;
while(scanf("%d%d",&n,&m)!=EOF){
memset(head,-1,sizeof(head));
cnt = 0;
for(i=0;i<n;i++){
add_edge(i,i+n,1);
add_edge(i+n,i,0);
}
for(i=0;i<m;i++){
scanf(" (%d,%d)",&a,&b);
add_edge(a+n,b,INF);
add_edge(b,a+n,0);
add_edge(b+n,a,INF);
add_edge(a,b+n,0);
}
int ans = INF;
nn = n * 2;
for(i=0;i<n;i++){
memset(vis,0,sizeof(vis));
for(j=head[i];j!=-1;j=edge2[j].next){
vis[edge2[j].v] = 1;
}
int sum = 0;
for(j=0;j<n;j++){
if(vis[j]) sum++;
}
if(sum < n - 1){
src = i + n;
break;
}
}
for(i=1;i<n;i++){
sink = i;
memcpy(edge,edge2,sizeof(node)*cnt);
int temp = isap();
ans = min(ans, temp);
}
if(ans == INF) ans = n;
printf("%d\n",ans);
}
return 0;
}

最新文章

  1. php 文件上传
  2. paper 127:机器学习中的范数规则化之(二)核范数与规则项参数选择
  3. VS中新建类
  4. web工程中URL地址的推荐写法
  5. 42.Android之ListView中ArrayAdapter简单学习
  6. navicat从下载到使用
  7. Delphi 如何清除动态数组的内存?
  8. Linux 网络编程 高级套接字
  9. jsp中四种传递参数的方法
  10. HDU 3335 Divisibility (DLX)
  11. PHP 切割字符串 点号 不用双斜杠
  12. Hdu3812-Sea Sky(深搜+剪枝)
  13. 【JAVA学习】“-Xmx1024m -Xms1024m -Xmn512m -Xss256k”——Java执行參数(转)
  14. python3的文件读写模式
  15. Java学习笔记之Scanner报错java.util.NoSuchElementException
  16. jsoup -- xml文档解析
  17. IIS Default Web Site : The service did not response to the start or control request in a timely fashion
  18. Win10电脑经常自动掉线、自动断网的解决方法
  19. C借函数指针构造映射
  20. 关于Oracle误操作--数据被Commit后的数据回退恢复(闪回)

热门文章

  1. CSS的引入方式和样式
  2. 【转】python 关键字
  3. 洛谷P5239 回忆京都
  4. java Timer定时器管理类
  5. node.js mongodb ReplSet
  6. spring RestTemplate 实例(NameValuePair)
  7. Linux内核中进程上下文和中断上下文的理解
  8. 关于python的hashlib md5的报错处理
  9. ubuntu16.04安装opencl
  10. caffe环境配置2