P1640 [SCOI2010]连续攻击游戏

题目链接

P1640 [SCOI2010]连续攻击游戏

思路

每件装备只能用一次,如果把攻击序列建成点,就是装备和攻击顺序的匹配。
比如属性值是\(3\)\(5\),那么这件装备要么在\(3\)位置要么在\(5\)位置被使用。
当然,按攻击顺序开始匹配,一旦匹配不成功,根据题意就必须中止。
每次都memset太慢了

代码

  • 40pts:
/*
@ author:pyyyyyy
-----知识点------
暴力dfs
-----debug-------

*/

#include<bits/stdc++.h>
using namespace std;
const int N=1000001;
int a[N],b[N],visit[N],ans,n;
void dfs(int now)
{
	if(now>=n) return ;
	if(now>ans) ans=now;
	for(int i=1;i<=n;++i)
		if(!visit[i]&&(a[i]==now+1||b[i]==now+1))
		{
			visit[i]=1;
			dfs(now+1);
			visit[i]=0;
		}
}
int main()
{
	cin>>n;
	for(int i=1;i<=n;++i)
		cin>>a[i]>>b[i];
	for(int i=1;i<=n;++i)
	{
		if(a[i]==1||b[i]==1)
		{
			visit[i]=1;
			dfs(1);
			visit[i]=0;
		}
	}
	cout<<ans;
	return 0;
}

  • 100pts:
/*
@ author:pyyyyyy
-----知识点------
二分图最大匹配,把每个武器和他的属性连起来求最大匹配 
-----debug-------
memset导致tle,可以用时间戳优化 
*/

#include<bits/stdc++.h>
#include<stack> 
#define MAXN  1010005
using namespace std;
vector<int> G[10005];    
int visit[MAXN];                
int v[MAXN];                   
int maxn;                             
int n;  
stack<int> q;
int match(int u)
{
	for(int i=0;i<G[u].size();++i)
	{
		int to=G[u][i];
		if(visit[to]) continue;
		visit[to]=1;
		q.push(to);
		if(!v[to]||match(v[to]))
		{
			v[to]=u;
			return 1;
		}
	}
	return 0;
}
void work()
{
	memset(v,0,sizeof(v));
	memset(visit,0,sizeof(visit));
	int sum=0;
	for(int i=1;i<=maxn;++i)
	{
		if(match(i)) sum++;
		else break;
		while(!q.empty()){
			visit[q.top()]=0;
			q.pop();
		}
	}
	cout<<sum;
}
int main()
{
	cin>>n;
	maxn=0;
	for(int i=1;i<=n;++i)
	{
		int u,v;
		scanf("%d%d",&u,&v);
		maxn=max(maxn,u),maxn=max(maxn,v);
		G[u].push_back(i+10000),G[v].push_back(i+10000);
	}
	work();
	return 0;
}
posted @ 2020-02-28 21:31  pyyyyyy  阅读(131)  评论(0编辑  收藏  举报