foj Problem 2232 炉石传说 福州大学第十三届程序设计竞赛_重现 二分图

题意:有两组士兵,分别为a和b,一对一互相攻打,每个士兵的生命值等于对方的攻击值减掉自己的生命值,问能否在a组士兵全部存活的情况下,b组全部阵亡


思路:比赛时没做出来,后来听到队长说是简单的二分图,就补了这方面的知识,对于a每一个士兵,在b中找到所有他能杀死别人且自己不死的士兵,这两者建一条从a->b的边,

就是求最大匹配数目是否达到n,如果达到,输出Yes,否则输出No, solve里的代码可以当做求最大匹配数的dfs模板


题目链接:http://acm.fzu.edu.cn/problem.php?pid=2232


#include <cstdio>
#include <cstring>
#include <algorithm>

#pragma warning (disable: 4996)

using namespace std;

const int maxn = 1005;
const int maxm = 10005;

struct edge
{
	int u, v, next;
}e[maxm];
int head[maxn];
bool vis[maxn];
int n, cnt;
int a[maxn], b[maxn], c[maxn], d[maxn];
int from[maxn];

void init()
{
	cnt = 0;
	memset(head, -1, sizeof(head));
	memset(from, -1, sizeof(from));
	memset(vis, false, sizeof(vis));
}

void addedge(int u, int v)
{
	e[cnt].u = u, e[cnt].v = v, e[cnt].next = head[u], head[u] = cnt++;
}

bool dfs(int u)
{
	int v;
	for (int i = head[u]; i !=- 1; i = e[i].next)
	{
		v = e[i].v;
		if (!vis[v])
		{
			vis[v] = true;
			if (from[v] == -1 || dfs(from[v]))
			{
				from[v] = u;
				return true;
			}
		}
	}
	return false;
}

void solve()
{
	bool flag = true;
	for (int i = 1; i <= n; i++)
	{
		memset(vis, false, sizeof(vis));
		if (!dfs(i))
		{
			flag = false;
			puts("No");
			break;
		}
	}
	if (flag)
		puts("Yes");
}

void build()
{
	for (int i = 1; i <= n ; i++)
	{
  		for (int j = 1; j <= n; j++)
		{
			if (b[i] >= c[j] && a[i] > d[j])
				addedge(i, j + n);
		}
	}
}

void read()
{
	int ret1 = 1, ret2 = 1;
	scanf("%d", &n);//注意下输入
	for (int i = 1; i <= n * 2; i++)
	{
		if (i & 1)
			scanf("%d", &a[ret1++]);
		else
			scanf("%d", &b[ret2++]);
	}
	ret1 = ret2 = 1;
	for (int i = 1; i <= n * 2; i++)
	{
		if (i & 1)
			scanf("%d", &c[ret1++]);
		else
			scanf("%d", &d[ret2++]);
	}
}

int main()
{
	int t;
	scanf("%d", &t);
	while (t--)
	{
		init();
		read();//读入数据
		build();//建边
		solve();//求最大匹配
	}
	return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值