洛谷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 2
1 3
2 3
输出样例#1:  复制
1





解题思路:

       这题和1344很像都是转化成最大流来做,因为这题是最小割点数,然后我们要把最小割边转化成最小割点,就要拆点,把一个点拆成两个点,一个点连进边,一个点连出边,然后再这两个点之间连一条边权为1的边,因为一个点只能删一次,记得都要连接反边,比如:a-b,a-a+n-b-b+n-a,其中a-a+n和b-b+n要是边权为一,剩下的边应该是作为联通的,所以边权应该是无穷大,反边为0,接下来就是从起点s+n,到t,跑一遍最大流,其实我还是没懂为什么是s+n,有空理解一下。。。

代码:

#include <iostream>
#include <cstring>
#include <string>
#include <algorithm>
#include <cmath>
#include <queue>
#define inf 0x3f3f3f3f
using namespace std;
int h[2000],dis[2000],s,t,n,m,cnt=-1;
struct newt{
	int to,net,cost;
}e[4000];
inline void addedge(int u,int v,int val)
{
	e[++cnt].to=v,e[cnt].net=h[u],e[cnt].cost=val,h[u]=cnt;
}
queue<int>q;
inline bool bfs()
{
	memset(dis,-1,sizeof(dis));
	q.push(s),dis[s]=0;
	while(!q.empty()){
		int u=q.front();q.pop();
		for(int i=h[u];i;i=e[i].net)
		if(dis[e[i].to]==-1&&e[i].cost>0)dis[e[i].to]=dis[u]+1,q.push(e[i].to);
	}
	return dis[t]!=-1;
}
inline int dfs(int u,int op)
{
	if(u==t)return op;
	int flow=0,used=0;
	for(int i=h[u];i;i=e[i].net)
	{
		int v=e[i].to;
		if(dis[v]==dis[u]+1&&e[i].cost>0)
		{
			used=dfs(v,min(op,e[i].cost));
			if(!used)continue;
			flow+=used,op-=used;
			e[i].cost-=used,e[i^1].cost+=used;
			if(!op)break;
		}
	}
	if(!flow)dis[u]=-1;
	return flow;
}
int main()
{
	int a,b,ans=0;
	cin>>n>>m>>a>>b;
	s=a+n;t=b;
	for(int i=1;i<=n;i++)
	{
		addedge(i,i+n,1);
		addedge(i+n,i,0);
	}
	for(int i=1;i<=m;i++)
	{
		cin>>a>>b;
		addedge(a+n,b,inf);
		addedge(b,a+n,0);
		addedge(b+n,a,inf);	
		addedge(b+n,a,0);
	}
	while(bfs())ans+=dfs(s,inf);
    printf("%d\n",ans);
	return 0;
}

猜你喜欢

转载自blog.csdn.net/qq_40400202/article/details/81054625