[SCOI2010]连续攻击游戏

link

本场考试洛谷难度评级最弱的一道,然而考场上只是敲了个暴力,就特别离谱。总结下来应该是我练题不够,毕竟二分图到现在为止还是只敲过模板,于是遇到稍微有点变通的题目就不会做了,这一点以后一定要弥补回来。

说回题目本身。这道题有一个限制,即每个武器只能被使用一次,而又因为每个武力值也只会使用一次,这就构成了一个一一对应的关系,于是乎题目要求就变成了一个求最大匹配数的问题。又由于显然武器集合与武力值集合并无交集,便可以抽象成二分图后用最大匹配来求解。然后就是要注意由于需要连续的一些数,我们应该从小到大依次枚举武力值,如果一个点时无法增广,退出循环即可,这是唯一与模板不同的地方。复杂度鬼知道,能过就行。

#include<cstdio>
//#define zczc
const int N=1000010;
const int M=1010;
inline void read(int &wh){
	wh=0;int f=1;char w=getchar();
	while(w<'0'||w>'9'){if(w=='-')f=-1;w=getchar();}
	while(w>='0'&&w<='9'){wh=wh*10+w-'0';w=getchar();}
	wh*=f;return;
}

int m,a,b;
struct edge{
	int t,next;
}e[N<<1];
int esum,head[N<<1];
inline void add(int fr,int to){
	e[++esum]=(edge){to,head[fr]};head[fr]=esum;
}

int c[N<<1],vis[N<<1],nt;
inline bool dfs(int wh){
	for(int i=head[wh],th;i;i=e[i].next){
		if(vis[th=e[i].t]==nt)continue;vis[th]=nt;
		//printf("now:%d %d %d\n",wh,th-N,c[th]);
		if(c[th]==0||dfs(c[th]))return c[th]=wh,true;
	}
	return false;
}

signed main(){
	
	#ifdef zczc
	freopen("in.txt","r",stdin);
	#endif
	
	read(m);
	for(int i=1;i<=m;i++){
		read(a);read(b);
		add(a,N+i);add(b,N+i);
	}
	int ans=0;
	for(int i=1;;i++){
		//printf("ans:%d %d\n",i,ans);
		++nt;
		if(dfs(i))ans++;
		else break;
	}
	printf("%d\n",ans);
	
	return 0;
}
posted @ 2022-03-05 13:40  Feyn618  阅读(44)  评论(0)    收藏  举报