P1345 [USACO5.4]奶牛的电信Telecowmunication【最小割】【最大流】

题目描述

农夫约翰的奶牛们喜欢通过电邮保持联系,于是她们建立了一个奶牛电脑网络,以便互相交流。这些机器用如下的方式发送电邮:如果存在一个由c台电脑组成的序列a1,a2,...,a(c),且a1与a2相连,a2与a3相连,等等,那么电脑a1和a(c)就可以互发电邮。

很不幸,有时候奶牛会不小心踩到电脑上,农夫约翰的车也可能碾过电脑,这台倒霉的电脑就会坏掉。这意味着这台电脑不能再发送电邮了,于是与这台电脑相关的连接也就不可用了。

有两头奶牛就想:如果我们两个不能互发电邮,至少需要坏掉多少台电脑呢?请编写一个程序为她们计算这个最小值。

以如下网络为例:

1* / 3 - 2*

这张图画的是有2条连接的3台电脑。我们想要在电脑1和2之间传送信息。电脑1与3、2与3直接连通。如果电脑3坏了,电脑1与2便不能互发信息了。

输入格式

第一行 四个由空格分隔的整数:N,M,c1,c2.N是电脑总数(1<=N<=100),电脑由1到N编号。M是电脑之间连接的总数(1<=M<=600)。最后的两个整数c1和c2是上述两头奶牛使用的电脑编号。连接没有重复且均为双向的(即如果c1与c2相连,那么c2与c1也相连)。两台电脑之间至多有一条连接。电脑c1和c2不会直接相连。

第2到M+1行 接下来的M行中,每行包含两台直接相连的电脑的编号。

输出格式

一个整数表示使电脑c1和c2不能互相通信需要坏掉的电脑数目的最小值。

输入输出样例

输入 #1
3 2 1 21 32 3
输出 #1
1


思路
  肯定是最小割,直接交不要怂
  观察一下,这是蓝题,不会有这样的送分题的。
  再观察一下,发现踩烂的是电脑。
  所以就变成了求最小割点。不是tarjan
  最小割点的求法: 把每个点拆成流入流出两个点, 中间连一条费用为 1 的边,这条边被破坏即这个点被破坏。
  点与点之间理所应当连inf的容量,保证不会把连线给拆了。
CODE

  
技术图片
技术图片

 1 #include <bits/stdc++.h> 2 #define dbg(x) cout << #x << "=" << x << endl 3 #define eps 1e-8 4 #define pi acos(-1.0) 5  6 using namespace std; 7 typedef long long LL; 8  9 template<class T>inline void read(T &res) 10 { 11 char c;T flag=1; 12 while((c=getchar())<0||c>9)if(c==-)flag=-1;res=c-0; 13 while((c=getchar())>=0&&c<=9)res=res*10+c-0;res*=flag; 14 } 15  16 namespace _buff { 17 const size_t BUFF = 1 << 19; 18 char ibuf[BUFF], *ib = ibuf, *ie = ibuf; 19 char getc() { 20 if (ib == ie) { 21 ib = ibuf; 22 ie = ibuf + fread(ibuf, 1, BUFF, stdin); 23  } 24 return ib == ie ? -1 : *ib++; 25  } 26 } 27  28 int qread() { 29 using namespace _buff; 30 int ret = 0; 31 bool pos = true; 32 char c = getc(); 33 for (; (c < 0 || c > 9) && c != -; c = getc()) { 34 assert(~c); 35  } 36 if (c == -) { 37 pos = false; 38 c = getc(); 39  } 40 for (; c >= 0 && c <= 9; c = getc()) { 41 ret = (ret << 3) + (ret << 1) + (c ^ 48); 42  } 43 return pos ? ret : -ret; 44 } 45  46 const int maxn = 1e4 + 7; 47 const int inf = 0x3f3f3f3f; 48  49 int n,m,cnt = 1,s,t; 50  51 int maxflow; 52 int head[maxn]; 53  54 struct Node { 55 int v,dis,nxt; 56 }edge[maxn << 2]; 57  58 void BuildGraph(int u,int v,int dis){ 59 edge[++cnt].nxt = head[u]; 60 edge[cnt].v = v; 61 edge[cnt].dis = dis; 62 head[u] = cnt; 63  64 edge[++cnt].nxt = head[v]; 65 edge[cnt].v = u; 66 edge[cnt].dis = 0; 67 head[v] = cnt; 68 } 69  70 int depth[maxn]; 71  72 bool bfs() { 73 queue<int> q; 74 while(!q.empty()) 75  q.pop(); 76 memset(depth,0,sizeof(depth)); 77 depth[s] = 1; 78  q.push(s); 79 while(!q.empty()){ 80 int u = q.front(); 81  q.pop(); 82 for(int i = head[u]; i; i = edge[i].nxt){ 83 int v = edge[i].v; 84 if(edge[i].dis && !depth[v]){ 85 depth[v] = depth[u] + 1; 86 if(v == t) 87 return true; 88  q.push(v); 89  } 90  } 91  } 92 return false; 93 } 94  95 int Dinic(int u,int flow) {//最大流 96 if(u == t) 97 return flow; 98 int rest = flow,temp;//残量网络 99 for(int i = head[u];i;i = edge[i].nxt) {100 int v = edge[i].v;101 if(depth[v] == depth[u] + 1 && edge[i].dis){102 temp = Dinic(v,min(rest,edge[i].dis));103 if(!temp)depth[v] = 0;104 rest -= temp;105 edge[i].dis -= temp;106 edge[i ^ 1].dis += temp;107  }108  }109 return flow - rest;110 }111 112 int main(){113 scanf("%d %d %d %d",&n, &m, &s, &t);114 for(int i = 1;i <= n;i++){115 BuildGraph(i, i + n, 1);116  }117 118 int u,v;119 for(int i = 1; i <= m; i++){120 scanf("%d %d",&u, &v);121 BuildGraph(u + n,v,inf);122 BuildGraph(v + n,u,inf);123  }124 s += n;125 int flow = 0;126 while(bfs()){127 while(flow = Dinic(s,inf))128 maxflow += flow;129  }130 printf("%d\n",maxflow);131 return 0;132 }

View Code

 

相关文章