張江蔡

HaneDaniko發表於2024-06-27

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

相關文章