二分图判定+二分图最大匹配

判定
模板

邻接表

#include
using namespace std;
int n,m;
vector node[205];       //一个神奇的模拟邻接表的“超方便”的东西 
int colour[205];



bool dfs(int a,int c)
{
	colour[a]=c;
	for(int i=0;i>n>>m;
	for(int i=1;i<=m;i++) node[i].clear();
	for(int i=1;i<=m;i++)
	{
		int u,v;
		cin>>u>>v;
		node[u].push_back(v);
		node[v].push_back(u);
	}
	for(int i=0;i

邻接矩阵

#include
using namespace std;
int n,m;
int edge[205][205];
int colour[205];



bool dfs(int a,int c)
{
	colour[a]=c;
	for(int i=0;i>n>>m;
	for(int i=1;i<=m;i++)
	{
		int u,v;
		cin>>u>>v;
		edge[u][v]=1;
		edge[v][u]=1;
	}
	for(int i=0;i

例题
题目描述

S S城现有两座监狱,一共关押着N N名罪犯,编号分别为1-N1−N。他们之间的关系自然也极不和谐。很多罪犯之间甚至积怨已久,如果客观条件具备则随时可能爆发冲突。我们用“怨气值”(一个正整数值)来表示某两名罪犯之间的仇恨程度,怨气值越大,则这两名罪犯之间的积怨越多。如果两名怨气值为cc 的罪犯被关押在同一监狱,他们俩之间会发生摩擦,并造成影响力为c c的冲突事件。

每年年末,警察局会将本年内监狱中的所有冲突事件按影响力从大到小排成一个列表,然后上报到S 城Z 市长那里。公务繁忙的Z 市长只会去看列表中的第一个事件的影响力,如果影响很坏,他就会考虑撤换警察局长。

在详细考察了NN 名罪犯间的矛盾关系后,警察局长觉得压力巨大。他准备将罪犯们在两座监狱内重新分配,以求产生的冲突事件影响力都较小,从而保住自己的乌纱帽。假设只要处于同一监狱内的某两个罪犯间有仇恨,那么他们一定会在每年的某个时候发生摩擦。

那么,应如何分配罪犯,才能使Z 市长看到的那个冲突事件的影响力最小?这个最小值是多少?

输入输出格式

输入格式:
每行中两个数之间用一个空格隔开。第一行为两个正整数N,MN,M,分别表示罪犯的数目以及存在仇恨的罪犯对数。接下来的MM行每行为三个正整数a_j,b_j,c_ja
j
​ ,b
j
​ ,c
j
​ ,表示a_ja
j
​ 号和b_j b
j
​ 号罪犯之间存在仇恨,其怨气值为c_jc
j
​ 。数据保证1

输出格式:
共11 行,为ZZ 市长看到的那个冲突事件的影响力。如果本年内监狱中未发生任何冲突事件,请输出00。

输入输出样例

输入样例#1: 复制
4 6
1 4 2534
2 3 3512
1 2 28351
1 3 6618
2 4 1805
3 4 12884
输出样例#1: 复制
3512
说明

【输入输出样例说明】罪犯之间的怨气值如下面左图所示,右图所示为罪犯的分配方法,市长看到的冲突事件影响力是35123512(由22 号和33 号罪犯引发)。其他任何分法都不会比这个分法更优。

【数据范围】

对于30%30%的数据有N≤ 15N≤15。

对于70%70%的数据有N≤ 2000,M≤ 50000N≤2000,M≤50000。

对于100%100%的数据有N≤ 20000,M≤ 100000N≤20000,M≤100000。

贪心+并查集

#include
using namespace std;
int n,m;
int father[20010],fight[20010]; 
struct abc
{
	int from,to,w;
}edge[100010];
bool cmp(abc a,abc b)
{
	return a.w>b.w;
}
int getfather(int a)
{
	if(father[a]==a) return a;
	return getfather(father[a]);
}
void unionn(int a,int b)
{
	int fa=getfather(a);
	int fb=getfather(b);
	if(fa!=fb) father[fa]=fb;
}

int main()
{
	cin>>n>>m;
	for(int i=1;i<=m;i++)
	{
		cin>>edge[i].from>>edge[i].to>>edge[i].w;
	}
	for(int i=1;i<=n;i++) father[i]=i;
	sort(edge+1,edge+1+m,cmp);
	for(int i=1;i<=m+1;i++)
	{
		int u=edge[i].from;
		int v=edge[i].to;
		if(getfather(u)==getfather(v))
		{
			cout<

二分判定+二分答案

#include
using namespace std;
int n,m;
bool flag;
vector node[20010];
int colour[20010];
struct abc
{
	int from,to,w;
}edge[100010];
bool cmp(abc a,abc b)
{
	return a.w>n>>m;
	for(int i=1;i<=m;i++)
	{
		cin>>edge[i].from>>edge[i].to>>edge[i].w;
	}
	sort(edge+1,edge+1+m,cmp);
	int mid,l=0,r=m;
	while(l

二分图最大匹配

过山车
#include
using namespace std;
int m,n,k,x,y;
vector e[505];
int match[505],used[505];

bool dfs(int x)
{
for(int i=0;i {
if(!used[e[x][i]])
{
used[e[x][i]]=1;
if(match[e[x][i]]==0||dfs(match[e[x][i]]))
{
match[e[x][i]]=x;
return 1;
}
}
}
return 0;
}

int main()
{
cin>>m>>n>>k;
for(int i=1;i<=k;i++)
{
cin>>x>>y;
e[x].push_back(y);
}
memset(match,0,sizeof(match));
int sum=0;
for(int i=1;i<=m;i++)
{
memset(used,0,sizeof(used));
if(dfs(i)) sum++;
}
cout< return 0;
}

地鼠
描述

在避免了犬类的威胁后,地鼠家族必须面对一个新的捕食者。

这是n个地鼠洞和m个地鼠洞,每个洞在不同的(x, y)坐标上。
一只鹰来了,如果一只地鼠在几秒钟内没有到达一个洞,它很容易被吃掉。
一个洞最多只能救一只地鼠。
所有的地鼠都以同样的速度奔跑v.地鼠家族需要一种能使易受攻击的地鼠数量最小化的逃跑策略。
输入

输入包含几种情况。
每种情况的第一行包含四个小于100的正整数:n、m、s和v。接下来的n行给出了地鼠的坐标;
下面m行给出了地鼠洞的坐标。
所有距离均以米为单位;
所有的时间都是以秒为单位的;
所有速度都是米每秒。
输出

每种情况的输出由一行组成,给出了易受攻击的地鼠的数量。
样例输入

2,2,5 10
1.0 - 1.0
2.0 - 2.0
100.0 - 100.0
20.0 - 20.0
样例输出

1

#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
using namespace std;

double n,m,s,v,sum=0;
struct abc{
	double x,y;
}gop[100005];
abc hol[100005];
int edge[1005][1005];
int match[100005],used[100005];


bool dfs(int x)
{
	for(int i=1;i<=m;i++)
	{
		if(edge[x][i]==1)
		{
			if(!used[i])
			{
				used[i]=1;
				if(match[i]==0||dfs(match[i]))
				{
					match[i]=x;
					return 1;
				}
			}
		}
	}
	return 0;
}

int main()
{
	while(cin>>n>>m>>s>>v)
	{
		memset(edge,0,sizeof(edge));
		for(int i=1;i<=n;i++)
		{
			cin>>gop[i].x>>gop[i].y;
		}
		for(int i=1;i<=m;i++)
		{
			cin>>hol[i].x>>hol[i].y;
		}
		for(int i=1;i<=n;i++)
		{
			for(int j=1;j<=m;j++)
			{
				double w=sqrt((gop[i].x-hol[j].x)*(gop[i].x-hol[j].x)+(gop[i].y-hol[j].y)*(gop[i].y-hol[j].y));
	    		if((w/v)<=s) edge[i][j]=1;
			}
		}
		memset(match,0,sizeof(match));
		sum=0;
		for(int i=1;i<=n;i++)
		{
			memset(used,0,sizeof(used));
			if(dfs(i)) sum++;
		}
		cout<

你可能感兴趣的:(二分图判定+二分图最大匹配)