栏目分类:
子分类:
返回
名师互学网用户登录
快速导航关闭
当前搜索
当前分类
子分类
实用工具
热门搜索
名师互学网 > IT > 软件开发 > 后端开发 > C/C++/C#

网络流——刷题记录

C/C++/C# 更新时间: 发布时间: IT归档 最新发布 模块sitemap 名妆网 法律咨询 聚返吧 英语巴士网 伯小乐 网商动力

网络流——刷题记录

POJ 3041 Asteroids

链接
简述:
N*N的坐标系,有K颗行星,一次可以消灭一行或者一列行星,最少需要几次?
方案:
以横坐标方向和纵坐标方向的坐标为点,建立顶点两个顶点集,行星(x,y)则变成由横坐标点x指向纵坐标y的点,进行一个二分图的建立
二分图中,最小顶点覆盖等于最大匹配,因此问题可以变成一个二分图匹配问题。
最后使用网络流求解。
代码:

#include
#include
#include
#include
#include
#include
#include
#include

#define fast ios::sync_with_stdio(false), cin.tie(0), cout.tie(0)
#define ll long long
#define endl "n"
#define pii pair
#define pb push_back
#define debug(x) cout << "visit:" << x << endl
#define inf 2147483647

using namespace std;

//白书的dinic板子 
struct edge
{
	int to, cap, rev;
};

const int MAX_V = 1e3+5;

vector G[MAX_V];
int level[MAX_V];
int iter[MAX_V];

void add_edge(int from,int to,int cap)
{
	G[from].push_back( (edge){to,cap,G[to].size()});
	G[to].push_back( (edge){from,0,G[from].size()-1});
}

//标记距离 
void bfs(int s)
{
	for(int i=0;i que;
	level[s] = 0;
	que.push(s);
	while(que.size()>0)
	{
		int v = que.front();
		que.pop();
		for(int i=0;i0&&level[e.to]<0)
			{
				level[e.to] = level[v]+1;
				que.push(e.to);
			}
		}
	}
}

//寻找增广路 
int dfs(int v,int t,int f)
{
	if(v==t)
	{
		return f;
	}
	for(int &i=iter[v];i0&&level[v]0)
			{
				e.cap -= d;
				G[e.to][e.rev].cap += d;
				return d;
			}
			
		}
	}
	return 0;
}

int max_flow(int s,int t)
{
	int flow = 0;
	while(1)
	{
		bfs(s);
		if(level[t]<0)//不再可达,说明已经是最大流 
		{
			return flow;
		}
		for(int i=0;i0)
		{
			flow += f;
		}
	}
}

int main()
{
	int s, t;
	int n, k;
	scanf("%d %d",&n,&k);
	s = 0;
	t = 2*n+1;
	for(int i=1;i<=n;++i)
	{
		add_edge(s,i,1);
	}
	for(int i=1;i<=n;++i)
	{
		add_edge(i+n,t,1);
	}
	for(int i=1;i<=k;++i)
	{
		int x, y;
		scanf("%d %d",&x,&y);
		add_edge(x,y+n,1);
	}
	printf("%dn",max_flow(s,t));
	return 0;
}

转载请注明:文章转载自 www.mshxw.com
本文地址:https://www.mshxw.com/it/718172.html
我们一直用心在做
关于我们 文章归档 网站地图 联系我们

版权所有 (c)2021-2022 MSHXW.COM

ICP备案号:晋ICP备2021003244-6号