张江蔡

A.匹配

显然这个题可以用哈希,也不用预处理,直接 \(O(1)\) 拓展就行了. \(A\) 拓展用 \(f'=f\times sum+A_{i}\)\(B\)\(f'=f+B_{i}\times num^{i}\),自然溢出就行.

#include<bits/stdc++.h>
using namespace std;
#define speed ios::sync_with_stdio(false);
#define input(i) int (i);cin>>(i)
#define tests int cases;cin>>cases;while(cases--)
typedef unsigned long long hdk;
string a,b;char ch;
const hdk num=233;
hdk ah,bh,bnum=1,anow,bnow;
inline hdk ahash(){
	ah=ah*num+a[anow];
	++anow;return ah;
}
inline hdk bhash(){
	bh+=bnum*b[bnow];
	--bnow;bnum*=num;
	return bh;
}
inline void clear(){
	ah=0;bh=0;bnum=1;anow=0;bnow=b.length()-1;
}
signed main(){
	#ifdef ONLINE_JUDGE
	freopen("string.in","r",stdin);
	freopen("string.out","w",stdout);
	#endif
	speed tests{
		input(la);input(lb);
		cin>>a;
		b=a.substr(0,lb);
		cin>>ch;b.push_back(ch);
		clear();
		int ans=0;
		for(int i=1;i<=b.length();++i){
			hdk m=ahash(),n=bhash();
			if(m==n) ans=i;
		}
		cout<<ans<<endl;
	}
}

B.回家

赛时打的是Tarjan割点,以为是纯板子,然后发现单纯割点跑不对(谴责这个堂食样例跑什么都能过),自己搓了一组数据才发现,割点不一定割的是 \(1\)\(n\) 的路径,统计这个答案必须要保证它割的这两部分一个包含 \(1\) 另一个包含 \(n\) 才行. 所以就在 tarjan 里套了个 dfs 然后递归炸了. 后来想到 tarjan 不就是搜吗然后爆改 tarjan 拿了 \(60\)

赛时代码


#include <bits/stdc++.h>
using namespace std;
#define speed ios::sync_with_stdio(false);
#define input(i) int (i);cin>>(i)
#define tests int cases;cin>>cases;while(cases--)
int n,m;
struct node{
	int dfn,low,vis;
	bool cut;
}p[200001];
struct hdk{
	int to,nxt;
}e[200001];
int head[200001],cnt,enow;
inline void add(int x,int y){
	e[++enow]={y,head[x]};
	head[x]=enow;
}
bool tarjan(int s,int root){
	++cnt;
	p[s].dfn=cnt;
	p[s].low=cnt;
	int child=0;
	bool totcheck=false;
	for(int i=head[s];i;i=e[i].nxt){
		int tem=e[i].to;
		if(p[tem].dfn==0){
			++child;
			bool check=tarjan(tem,s);
			if(check) totcheck=true;
			p[s].low=min(p[s].low,p[tem].low);
			if(p[s].dfn<=p[tem].low){
				if(s!=root||child>1){
					if(check){
						p[s].cut=1;
					}
				}
			}
		}
		else{
			p[s].low=min(p[s].low,p[tem].dfn);
		}
	}
	if(s==n) return true;
	return totcheck;
}
signed main(){
	#ifdef ONLINE_JUDGE
	freopen("home.in","r",stdin);
	freopen("home.out","w",stdout);
	#endif
	speed tests{
		cnt=0;enow=0;
		memset(p,0,sizeof p);
		memset(e,0,sizeof e);
		memset(head,0,sizeof head);
	    cin>>n>>m;
	    for(int i=1;i<=m;++i){
	    	input(x);input(y);
	        add(x,y);add(y,x);
	    }
	    tarjan(1,1);
	    int ans=0;
		vector<int>an;
	    for(int i=2;i<=n-1;++i){
	    	if(p[i].cut){
	    		ans++;
	    		an.push_back(i);
			}
		}
		cout<<ans<<endl;
		bool flg=false;
		if(!an.empty()){
			for(int i:an){
				if(flg) cout<<" ";
				cout<<i;
				flg=true;
			}
		}
		cout<<endl;
	}
}

那么错哪了呢,显然是统计多了,因为我是从 \(1\) 搜过来的,所以忘记判 \(1\) 是不是在另一边了

但是这样的话就不用爆改 tarjan 了,写个 check 搞一下就行了.

考虑到如果 \(dfn[v]>dfn[u]\),则 \(v\)\(u\) 的搜索子树中,所以我们需要找出一个点满足下面的条件:

  1. \(v\)\(1\) 的搜索子树中
  2. \(v\) 不在 \(n\) 的搜索子树中

或者 \(1\)\(n\) 反过来也行.

所以跑个割点的基础上判个 \(dfn\) 就行了

#include<bits/stdc++.h>
using namespace std;
bool sc=false;
#define tests int cases;cin>>cases;while(cases--)
#define speed ios::sync_with_stdio(false);
#define input(i) int (i);cin>>(i)
#define debug(i) if(sc)cout<<(i)<<endl
#define clears(i) memset((i),0,sizeof (i))
inline void start(){
	#ifndef ONLINE_JUDGE
	sc=true;
	freopen("a.in","r",stdin);
	freopen("a.out","w",stdout);
	#endif
	#ifdef ONLINE_JUDGE
	freopen("home.in","r",stdin);
	freopen("home.out","w",stdout);
	#endif
	string x="[TEST]";
	debug(x);
	debug(time(0));
}
vector<int>an;
int head[2000001],enow;
int n,m;
struct edge{
	int u,v,next;
}e[800001];
inline void add(int u,int v){
	e[++enow]={u,v,head[u]};
	head[u]=enow;
	return;
}
int dfn[200001],low[200001],cnt;
inline int check(int u,int v){
	if(dfn[v]<=dfn[1]&&dfn[v]>dfn[n]) return 1;
	if(dfn[v]<=dfn[n]&&dfn[v]>dfn[1]) return 1;
	return 0;
}
void tarjan(int u,int fa){
	dfn[u]=low[u]=++cnt;
	for(int i=head[u];i;i=e[i].next){
		int v=e[i].v;
		if(!dfn[v]){
			tarjan(v,u);
			low[u]=min(low[u],low[v]);
			if(low[v]>=dfn[u]&&u!=1&&u!=n&&check(u,v)){
				an.push_back(u);
			}
		}
		else if(v!=fa) low[u]=min(low[u],dfn[v]);
	}
	return;
}
inline void clearall(){
	clears(e);
	clears(head);
	clears(low);
	clears(dfn);
	enow=0;
	cnt=0;
	an.clear();
}
signed main(){
	start();
	speed tests{
		clearall();
		cin>>n>>m;
		while(m--){
			int u,v;
			cin>>u>>v;
			add(u,v);
			add(v,u);
		}
		tarjan(1,0);
		sort(an.begin(),an.end());
		cout<<an.size()<<endl;
		for(int i:an){
			cout<<i<<" ";
		}
		cout<<endl;
	}
}

C.寿司

To be added

posted @ 2024-06-27 09:34  HaneDaniko  阅读(54)  评论(2编辑  收藏  举报