JZOJ 1610. 【东莞市选2008】导弹


题目:

在这里插入图片描述


题意:

给出每个节点到其他节点的权值,再让你构建一个二分图,要求其最大匹配最小


分析:

因为 n &lt; = 100 n&lt;=100 n<=100,所以我们可以直接用 F l o y d Floyd Floyd预处理出每个点到其他点的最短路
然后就是用二分确定我们的二分图的最大边值,在二分的 c h e c k check check函数中使用匈牙利算法求最大匹配


代码:

#include<iostream>
#include<cstdio>
#include<cmath>
#include<cstring>
#include<cstdlib>
#include<algorithm>
#include<set>
#include<queue>
#include<vector>
#include<map>
#include<list>
#include<ctime>
#include<iomanip>
#include<string>
#include<bitset>
#include<deque>
#include<set>
#define LL long long
using namespace std;
inline LL read(){
    LL d=0,f=1;char s=getchar();
    while(s<'0'||s>'9'){if(s=='-')f=-1;s=getchar();}
    while(s>='0'&&s<='9'){d=d*10+s-'0';s=getchar();}
    return d*f;
}
int t[105][105],m1,m2;
int c1[105],c2[105],tf[105];
struct node{
	int to,next;
}e[10005];
int cnt=0,ls[205],HZB[105];
void add(int x,int y)
{
	e[cnt]=(node){y,ls[x]};
	ls[x]=cnt++;
	return;
}
bool dfs(int k)
{
	for(int i=ls[k];~i;i=e[i].next)
	{
		int s=e[i].to;
		if(!tf[s])
		{
			tf[s]=1;
			if(!HZB[s]||dfs(HZB[s])) {HZB[s]=k;return 1;}
		}
	}
	return 0;
}
bool check(int x)
{
	memset(ls,-1,sizeof(ls));
	memset(HZB,0,sizeof(HZB));
	cnt=0;
	for(int i=1;i<=m1;i++)
	  for(int j=1;j<=m2;j++)
	    if(t[c1[i]][c2[j]]<=x) add(i,j);
	int sum=0;
	for(int i=1;i<=m1;i++)
	{
		memset(tf,0,sizeof(tf));
		if(dfs(i)) sum++;
	}
	return sum==m2;
}
int main()
{
//	freopen("c.in","r",stdin);
//	freopen("c.out","w",stdout);
	int n=read();
	memset(t,0x3f3f3f3f,sizeof(t));
	for(int i=1;i<=n;i++)
	  for(int j=1;j<=n;j++)
	    t[i][j]=read();
	for(int k=1;k<=n;k++)
	  for(int i=1;i<=n;i++)
	    for(int j=1;j<=n;j++)
	      t[i][j]=min(t[i][j],t[i][k]+t[k][j]);
	m1=read(); for(int i=1;i<=m1;i++) c1[i]=read();
	m2=read(); for(int i=1;i<=m2;i++) c2[i]=read();
	int l=1,r=1000000;
	while(l<=r)
	{
		int mid=(l+r)>>1;
		if(check(mid)) r=mid-1;
		else l=mid+1;
	}
	cout<<l;
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值