标签:
Time Limit: 1000MS | Memory Limit: 30000K | |
Total Submissions: 4678 | Accepted: 2163 |
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
【分析】
图的连通度分为点连通度和边连通度:
(1)点连通度:只许删点,求至少要删掉几个点(当然,s和t不能删去,这里保证原图中至少有三个点);
(2)边连通度:只许删边,求至少要删掉几条边。
并且,有向图和无向图的连通度求法不同,因此还要分开考虑(对于混合图,只需将其中所有的无向边按照
无向图的办法处理、有向边按照有向图的办法处理即可)。
【1】有向图的边连通度:
这个其实就是最小割问题。以s为源点,t为汇点建立网络,原图中的每条边在网络中仍存在,容量为1,求该网络的最小割(也就是最大流)的值即为原图的边连通度。
【2】有向图的点连通度:
需要拆点。建立一个网络,原图中的每个点i在网络中拆成i‘与i‘‘,有一条边<i‘,
i‘‘>,容量为1 (<s‘, s‘‘>和<t‘, t‘‘>例外,容量为正无穷)。原图中的每条边<i,
j>在网络中为边<i‘‘, j‘>,
容量为正无穷。以s‘为源点、t‘‘为汇点求最大流,最大流的值即为原图的点连通度。
说明:最大流对应的是最小割。显然,容量为正无穷的边不可能通过最小割,也就是原图中的边和s、t两个点不能删去;若边<i, i‘‘>通过最小割,则表示将原图中的点i删去。
【3】无向图的边连通度:
将图中的每条边(i, j)拆成<i, j>和<j, i>两条边,再按照有向图的办法(【1】)处理;
【4】无向图的点连通度:
将图中的每条边(i, j)拆成<i, j>和<j, i>两条边,再按照有向图的办法(【2】)处理。
#include <iostream> #include <cstring> #include <cstdio> #include <algorithm> #include <cmath> #include <string> #include <map> #include <queue> #include <vector> #define inf 0x7fffffff #define met(a,b) memset(a,b,sizeof a) typedef long long ll; using namespace std; const int N = 110; const int M = 24005; int n,m,cnt=0; int toto; struct man { int u,v; }mp[N*N]; struct Dinic { int s,t; struct Edge { int nxt,to,cap,flow; } edg[M]; bool vv[N]; bool vis[N]; int d[N]; int h[N]; int cur[N]; void init() { met(h,-1);toto=0; } void AddEdge(int x,int y,int z) { edg[toto].to=y; edg[toto].nxt=h[x]; edg[toto].cap=z;edg[toto].flow=0; h[x]=toto++; edg[toto].to=x;edg[toto].flow=0; edg[toto].nxt=h[y]; h[y]=toto++; } bool BFS() { memset(vis,0,sizeof(vis));met(d,-1); queue<int>q; q.push(s); d[s]=0; vis[s]=1; while (!q.empty()) { int x = q.front(); q.pop(); for (int i = h[x]; i!=-1; i=edg[i].nxt) { int v=edg[i].to; if (!vis[v] && edg[i].cap > edg[i].flow) { vis[v]=1; d[v] = d[x]+1; q.push(v); } } } return vis[t]; } int DFS(int x,int a) { if (x==t || a==0) return a; int flow = 0,f; for(int &i=cur[x]; i!=-1; i=edg[i].nxt) { int v=edg[i].to; if (d[x]+1 == d[v] && (f=DFS(v,min(a,edg[i].cap-edg[i].flow)))>0) { edg[i].flow+=f; edg[i^1].flow-=f; flow+=f; a-=f; if (a==0) break; } } return flow; } int Maxflow(int s,int t) { this->s=s; this->t=t; int flow = 0; while (BFS()) { for(int i=0; i<=2*n; i++)cur[i]=h[i]; flow+=DFS(s,inf); } return flow; } } dc; void Build() { dc.init(); for(int i=0;i<n;i++)dc.AddEdge(i,i+n,1); for(int i=0;i<m;i++){ dc.AddEdge(mp[i].u+n,mp[i].v,inf); dc.AddEdge(mp[i].v+n,mp[i].u,inf); } } int main() { int u,v; while(~scanf("%d%d",&n,&m)){ met(mp,0);int ans=inf;int pp[N][N]; met(pp,0); for(int i=0;i<m;i++){ scanf(" (%d,%d)",&u,&v); mp[i].u=u;mp[i].v=v;pp[u][v]=pp[v][u]=1; } for(int i=0;i<n;i++){ for(int j=i+1;j<n;j++){ Build(); if(!pp[i][j]){ans=min(ans,dc.Maxflow(i+n,j));if(ans==0)break;} } if(ans==0)break; } if(abs(ans)>=n)ans=n; printf("%d\n",ans); } return 0; }
POJ 1966 Cable TV Network(顶点连通度的求解)
标签:
原文地址:http://www.cnblogs.com/jianrenfang/p/5947469.html