张江蔡
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\) 的搜索子树中,所以我们需要找出一个点满足下面的条件:
- \(v\) 在 \(1\) 的搜索子树中
- \(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