POJ 1966

求的是无向图的点连通度。开始便想到网络流,既然选的是点,当然就要拆点加边了。但无论如何也不敢往枚举源汇点的方向想,因为网络流复习度很高。看看网上大牛的,都是枚举,再看数据,原来N才50个点,枚举无压力啊。看来自己以后要注意分析一下复杂度了。

 

总结:

1)无向图点连通度

看来没有什么好的算法。网络流。把点i拆成i->i‘容量自然是1,把无向图的边也拆成两条有向边i'->j,j'->i,容量为无穷。然后,枚举求s'->t的最小割就可了。

2)有向图点连通度

这个更简单了,单纯拆点建图就可以了。

3)无向图边连通度。

可以用store-wanger求最小割。边权为1

4)有向图边连通度

就是网络流求最小割

 

  1 #include <iostream>
  2 #include <cstdio>
  3 #include <cstring>
  4 #include <algorithm>
  5 using namespace std;
  6 
  7 const int INF=0x3f3f3f3;
  8 const int MAXN=120    ;
  9 const int MAXM=15000;
 10 
 11 struct Node{
 12     int from,to,next;
 13     int cap;
 14 }edge[MAXM];
 15 int tol;
 16 
 17 int dep[MAXN];
 18 int head[MAXN];
 19 bool maze[MAXN][MAXN];
 20 int n,m;
 21 void init(){
 22     tol=0;
 23     memset(head,-1,sizeof(head));
 24 }
 25 void addedge(int u,int v,int w){
 26     edge[tol].from=u;
 27     edge[tol].to=v; edge[tol].cap=w;  edge[tol].next=head[u];
 28     head[u]=tol++;
 29     edge[tol].from=v;
 30     edge[tol].to=u;
 31     edge[tol].cap=0;
 32     edge[tol].next=head[v];
 33     head[v]=tol++;
 34 }
 35 
 36 int BFS(int start,int end){
 37     int que[MAXN];
 38     int front,rear; front=rear=0;
 39     memset(dep,-1,sizeof(dep));
 40     que[rear++]=start;
 41     dep[start]=0;
 42     while(front!=rear){
 43         int u=que[front++];
 44         if(front==MAXN)front=0;
 45         for(int i= head[u];i!=-1; i=edge[i].next){
 46             int v=edge[i].to;
 47             if(edge[i].cap>0&& dep[v]==-1){
 48                 dep[v]=dep[u]+1;
 49                 que[rear++]=v;
 50                 if(rear>=MAXN) rear=0;
 51                 if(v==end)return 1;
 52             }
 53         }
 54     }
 55     return 0;
 56 }
 57 int dinic(int start,int end){
 58     int res=0;
 59     int top;
 60     int stack[MAXN];
 61     int cur[MAXN];
 62     while(BFS(start,end)){
 63         memcpy(cur,head, sizeof(head));
 64         int u=start;
 65         top=0;
 66         while(1){
 67             if(u==end){
 68                 int min=INF;
 69                 int loc;
 70                for(int i=0;i<top;i++)
 71                   if(min>edge [stack[i]].cap) {
 72                       min=edge [stack[i]].cap;
 73                       loc=i;
 74                   }
 75                 for(int i=0;i<top;i++){
 76                     edge[stack[i]].cap-=min;
 77                     edge[stack[i]^1].cap+=min;
 78                 }
 79                 res+=min;         
 80                 top=loc;               
 81                 u=edge[stack[top]].from;
 82             }
 83             for(int i=cur[u]; i!=-1; cur[u]=i=edge[i].next)
 84               if(edge[i].cap!=0 && dep[u]+1==dep[edge[i].to])
 85                  break;
 86             if(cur[u] !=-1){
 87                 stack [top++]= cur[u];
 88                 u=edge[cur[u]].to;
 89             }
 90             else{
 91                 if(top==0) break;
 92                 dep[u]=-1;
 93                 u= edge[stack [--top] ].from;
 94             }
 95         }
 96     }
 97     return res;
 98 }
 99 
100 void build(){
101         init();
102         for(int i=0;i<n;i++){
103             for(int j=0;j<n;j++){
104                 if(i==j)
105                 addedge(i*2,i*2+1,1);
106                 else if(maze[i][j]){
107                     addedge(i*2+1,j*2,INF);
108                 }
109             }
110         }
111 
112 }
113 
114 int main(){
115     int u,v;
116     while(scanf("%d%d",&n,&m)!=EOF){
117           memset(maze,false,sizeof(maze));
118         for(int i=0;i<m;i++){
119             scanf(" (%d,%d)",&u,&v);
120             maze[u][v]=maze[v][u]=true;
121         }
122         int ans=INF;
123         for(int i=0;i<n;i++){
124             for(int j=i+1;j<n;j++){
125                 build();
126                 if(!maze[i][j]){
127                 int res=dinic(i*2+1,j*2);
128                 if(res<ans) ans=res;
129                 if(ans==0) break;
130                 }
131             }
132             if(ans==0) break;
133         }
134         if(ans>=n){ printf("%d\n",n); continue; }
135         printf("%d\n",ans);
136     }
137     return 0;
138 }
View Code

转载于:https://www.cnblogs.com/jie-dcai/p/3860603.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值