2018.10.21 练习赛 树专练

T1 树

题解:

记录树上前缀和,每次加入新前缀和就二分一下前缀和数组看有无满足\(sum[now]-s\)的数在里面,因为\(sum\)必定是单调的,就乱搞完毕;

\(code\):

#include<cstdio>
#include<algorithm>
#include<ctype.h> 
#include<vector>
#include<queue>
#include<cstring>
#include<map>
#include<stdlib.h>
#include<ctime>
#define lowbit(x) (x&-x)
#define ll long long
#define ld double
#define mod 998244353 
using namespace std;

char buf[1<<20],*p1,*p2;
inline char gc()
{
    return getchar();
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}

template<typename T>
inline void read(T &x)
{
    char tt;
    bool flag=0;
    while(!isdigit(tt=gc())&&tt!='-');
    tt=='-'?(flag=1,x=0):(x=tt-'0');
    while(isdigit(tt=gc())) x=x*10+tt-'0';
    if(flag) x=-x;
}

const int maxn=1e5+2;
int n,s;
vector<int>G[maxn];
bool root[maxn];
int w[maxn],sum[maxn],ans;

void dfs(int x,int dep)
{
	sum[dep]=sum[dep-1]+w[x];
	if(sum[lower_bound(
	sum,sum+dep+1,sum[dep]-s)-sum]==sum[dep]-s) ans++;
	for(int i=G[x].size()-1;i>=0;i--)
	{
		int p=G[x][i];
		dfs(p,dep+1);
	}
	sum[dep]=0;
}

int main()
{
	read(n),read(s);
	for(int i=1;i<=n;i++) read(w[i]);
	for(int i=1;i<n;i++)
	{
		int x,y;
		read(x),read(y);
		G[x].push_back(y);
		root[y]=1;
	}
	for(int i=1;i<=n;i++)
	if(!root[i]) {dfs(i,1);break;}
	printf("%d",ans);
	return 0;
}

T2 联通块计数

题解:

树DP=_=

\(code:\)

#include<cstdio>
#include<algorithm>
#include<ctype.h> 
#include<vector>
#include<queue>
#include<cstring>
#include<map>
#include<stdlib.h>
#include<ctime>
#define lowbit(x) (x&-x)
#define ll long long
#define ld double
#define mod 998244353 
using namespace std;

char buf[1<<20],*p1,*p2;
inline char gc()
{
//    return getchar();
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}

template<typename T>
inline void read(T &x)
{
    char tt;
    bool flag=0;
    while(!isdigit(tt=gc())&&tt!='-');
    tt=='-'?(flag=1,x=0):(x=tt-'0');
    while(isdigit(tt=gc())) x=x*10+tt-'0';
    if(flag) x=-x;
}
inline ll add(ll a,ll b){return a+b<mod?a+b:a+b-mod;}
inline ll mul(ll a,ll b){return a*b<mod?a*b:a*b%mod;}
inline ll sub(ll a,ll b){return a-b<0?a-b+mod:a-b;}

const int maxn=2002;
struct node{
	ll x,id;
	inline node(ll a=0,ll b=0)
	{x=a,id=b;}
	inline bool operator<(node a)const
	{return x==a.x?a.id<a.id:x<a.x;}
}a[maxn];

ll n,k,ans,w[maxn];
vector<ll>G[maxn];
bool book[maxn];

ll dfs(ll x,ll pre,ll lim)
{
	int ret=1;
	for(int i=G[x].size()-1;i>=0;i--)
	{
		int p=G[x][i];
		if(p==pre||book[p]||w[p]>lim) continue;
		ret=mul(ret,dfs(p,x,lim));
	}
//	printf("%d\n",lim);
	return ret+=(pre!=0);
}

int main()
{
	read(n),read(k);
	for(int i=1;i<=n;i++)
	{
		ll x;
		read(x);w[i]=x;
		a[i]=node(x,i);
	}sort(a+1,a+1+n);
	for(int i=1;i<n;i++)
	{
		ll x,y;
		read(x),read(y);
		G[x].push_back(y);
		G[y].push_back(x);
	}
	for(int i=1;i<=n;i++)
	{
		if(book[a[i].id]) continue;
		book[a[i].id]=1;
		ans=add(ans,dfs(a[i].id,0,a[i].x+k));
//		printf("%d\n",ans);
	}
	printf("%lld",ans);
	return 0;
}

T3 电压

题解:

题意为去掉一条边,看此图是否仍为一个二分图;

我们考虑去掉的这条边必定是所有奇环的交,且不能在任何的偶环上,\(tarjan\)找出所有环(这里的所有环是指写出的算法所能找出的环,并非真正意义上的所有环)

每当我们遇到一条返祖边,差分记录环覆盖的边,统计答案时满足前面我们所给的条件即可;

我们发现当我们的搜索顺序不同时,我们所找出的环也不同,但是,这并不影响我们的结果,因为如果一结果对一种图成立,那么他必定对所有图成立;

\(code:\)

#include<cstdio>
#include<algorithm>
#include<ctype.h> 
#include<vector>
#include<queue>
#include<cstring>
#include<map>
#include<stdlib.h>
#include<ctime>
#define lowbit(x) (x&-x)
#define ll long long
#define ld double
#define mod 998244353 
using namespace std;

char buf[1<<20],*p1,*p2;
inline char gc()
{
//    return getchar();
    return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<20,stdin))==p1?0:*p1++;
}

template<typename T>
inline void read(T &x)
{
    char tt;
    bool flag=0;
    while(!isdigit(tt=gc())&&tt!='-');
    tt=='-'?(flag=1,x=0):(x=tt-'0');
    while(isdigit(tt=gc())) x=x*10+tt-'0';
    if(flag) x=-x;
}

struct node{
	int x,id;
	inline node(int a=0,int b=0)
	{x=a,id=b;}
};

const int maxn=1e5+2;
int n,m,dep[maxn],tot;
int cnt[maxn][2];
//0 1 odd
//0 0 eve
vector<node>G[maxn];
void dfs(int x,int pre)
{
	for(int i=G[x].size()-1;i>=0;i--)
	{
		int p=G[x][i].x,id=G[x][i].id;
		if(id==pre) continue;
		if(!dep[p])
		{
			dep[p]=dep[x]+1;dfs(p,id);
			cnt[x][0]+=cnt[p][0];
			cnt[x][1]+=cnt[p][1];
		}
		else if(dep[p]<=dep[x])
		{
			if((dep[x]-dep[p])&1) cnt[x][0]++,cnt[p][0]--;
			else cnt[x][1]++,cnt[p][1]--,tot++;
		}
	}
}

int main()
{
//	freopen("voltage.in","r",stdin);
	read(n),read(m);
	for(int i=1;i<=m;i++)
	{
		int x,y;
		read(x),read(y);
		G[x].push_back(node(y,i));
		G[y].push_back(node(x,i));
	}
	int ans=0;
	for(int i=1;i<=n;i++) if(!dep[i]) dep[i]=1,dfs(i,0);
	for(int i=1;i<=n;i++) if(dep[i]!=1&&!cnt[i][0]&&cnt[i][1]==tot) ans++;
	printf("%d",ans+(tot==1));
}
posted @ 2018-10-21 23:10  Katoumegumi  阅读(94)  评论(0编辑  收藏  举报
返回顶部