Processing math: 7%

noip模拟63

考试过程:这次考试四个题基本上都是计数题,我觉得不太可做,就按顺序开题。

首先是T1,瓶颈就在于找环,但是我想了半天,没什么思路,只会o(n)找环,但是这样做复杂度是n\times m的,可以获得10pts的高分,再加上一个特殊性质,最终我获得了20pts的高分

然后是T2,首先是考虑XIN队算法,但是这个暴搜和之前的不太一样,需要想一下。

冲完XIN队后我看了看后面两个题,无思路,就又回来想T2,看到特殊性质,我就想拿这一档的分,但是我理解错了,它说的是区间没有相交,我当时以为区间嵌套和相交是没有关系的,结果考完试后强者cty告诉我嵌套是包含于相交的,我谔谔。那这部分算是白打了,以后一定要理解题意。

T1 电机压制

思路:建一棵DFS树,则特殊边就全部为返祖边。
odd_u对结点u统计奇环,even_u统计偶环.设一条返祖边为 u -> v若它形成奇环,则odd[u]++,odd[v]--.
x的子树所有结点的odd之和,即为x ->fa这条边被多少奇环包含(利用差分前缀和的思想)
注意实现细节:
1.当只有一个奇环的时候需要特判一下最后那一条边是不是重边,如果是那就没有贡献,否则的话ans++
2.若自己的儿子对答案造成了贡献,但是自己和儿子的连边是重边,那么ans--
代码如下:

AC_code
#include<bits/stdc++.h>
#define re register int
#define ii inline int
#define iv inline void
#define mid ((l+r)>>1)
#define lc (rt<<1)
#define rc (rt<<1|1)
#define f() cout<<"fuck"<<endl
#define head headddd
#define next net
using namespace std;
const int N=2e5+10;
unordered_map<int,bool> mp[N],no[N];
int n,m,tot,num,com,ans,fw;
int to[N<<1],head[N],next[N<<1],deep[N];
int odd[N],even[N],ji[N];
bool vis[N],flag;
ii read()
{
	int x=0;char ch=getchar();bool f=1;
	while(ch<'0' or ch>'9')
	{
		if(ch=='-') f=0;
		ch=getchar();
	}
	while(ch>='0' and ch<='9')
	{
		x=(x<<1)+(x<<3)+(ch^48);
		ch=getchar();
	}
	return f?x:(-x);
}
iv add(int x,int y)
{
	to[++tot]=y;
	next[tot]=head[x];
	head[x]=tot;
}
iv dfs(int st,int f)
{
	vis[st]=1;
	deep[st]=deep[f]+1;
	for(re i=head[st];i;i=next[i])
	{	
		int p=to[i];
		if(p==f) continue;
		if(vis[p])
		{
			if(deep[p]>deep[st]) continue;
			if((deep[st]-deep[p]+1)&1) ++odd[st],--odd[p],++num;
			else ++even[st],--even[p],++com;
			continue;
		}
		dfs(p,st);
	}
}	
iv dfs2(int st,int f)
{
	vis[st]=1;
	for(re i=head[st];i;i=next[i])
	{
		int p=to[i];
		if(vis[p]) continue;
		dfs2(p,st);
		if(odd[p]==num and even[p]==0 and no[st][p]) --ans;
		odd[st]+=odd[p],even[st]+=even[p];
	}
	for(re i=head[st];i;i=next[i])
	{
		int p=to[i];
		if(vis[p] and deep[p]<deep[st] and no[st][p] and odd[st]==num and even[st]==0) flag=1;
	}
}
signed main()
{
	freopen("a.in","r",stdin),freopen("a.out","w",stdout);
	n=read(),m=read();
	int u,v;
	for(re i=1;i<=m;i++)
	{
		u=read(),v=read();
		if(mp[v].find(u)==mp[v].end()) add(u,v),add(v,u),mp[v][u]=mp[u][v]=1;	
		else
		{
			if(no[v][u]) fw++;
			else fw+=2;
			no[v][u]=no[u][v]=1;
		}
	}
	dfs(1,0);
	for(re i=1;i<=n;i++) vis[i]=0;
	dfs2(1,0);
	if(num!=0 or com!=0)
	{
		for(re i=2;i<=n;i++) if(odd[i]==num and even[i]==0) ++ans;
		if(num==1 and !flag) ans++;
	}
	else ans=m-fw;
	printf("%d\n",ans);
	return 0;
}

posted @   WindZR  阅读(52)  评论(0)    收藏  举报
编辑推荐:
· 当数据爆炸遇上SQL Server:优化策略全链路解析
· 记录一次线上问题排查:JDK序列化问题
· 微服务之间有哪些调用方式?
· 记一次SQL隐式转换导致精度丢失问题的排查
· dotnet 9 通过 AppHostRelativeDotNet 指定自定义的运行时路径
阅读排行:
· 一个基于 C# Unity 开发的金庸群侠传 3D 版,直呼牛逼!
· SQL Server 2025 中的改进
· 国内首个「混合推理模型」Qwen3深夜开源,盘点它的N种对接方式!
· 向商界大佬一样管理技术工作 - 以团队换将+技术重构为例
· 用c#从头写一个AI agent,实现企业内部自然语言数据统计分析(三)--一个综合的例子
点击右上角即可分享
微信分享提示