C题 Concatenation
思路:给出几个数字段,求能组成的字典序最小的字符串。用sort使得组合完的字符串序列字典序最小即可。
#include<bits/stdc++.h>
using namespace std;
const int N=2e6;
string s[N];
bool cmp(string a,string b){
return a+b<b+a;
}
int n;
int main(){
ios::sync_with_stdio(false);
cin.tie(0),cout.tie(0);
cin>>n;
for(int i=0;i<n;i++){
cin>>s[i];
}
sort(s,s+n,cmp);
for(int i=0;i<n;i++)
cout<<s[i];
}
A题 Ancestor
题意:给你两棵树A和B,点的编号从1到n,根结点是1,且每个点都有一个价值,现在给你k个点,选任意k-1个不同的点,分别求这些点在两颗树上的最近公共祖先fa, fb,问存在多少种情况满足A树上fa的价值大于B树上fb的价值。
思路:有一个结论是:求树上多个点的LCA的方法是求这些点在树上的dfs序的最小值的点和最大值的点的LCA。所以我们求出来两颗树的dfs序后,将k个点按照dfs序的大小来排序后,离线处理,再按照上面的结论进行计算就行。
#include<bits/stdc++.h>
#define pb push_back
using namespace std;
const int N=1e5+9;
int n,k,ans;
int a[N],v[N],f[N],g[N],st[N][21],d[N],p[N][2];
vector<int>e[N];
void dfs(int x,int fa){
d[x]=d[fa]+1; st[x][0]=fa;
for(int y:e[x])
if(y!=fa)
dfs(y,x);
}
void buildst(){
for(int j=1;j<=20;j++)
for(int i=1;i<=n;i++)
st[i][j]=st[st[i][j-1]][j-1];
}
int LCA(int x,int y){
if(d[x]<d[y]) swap(x,y);
for(int i=20;i>=0;i--)
if(d[st[x][i]]>=d[y])
x=st[x][i];
if(x==y) return x;
for(int i=20;i>=0;i--)
if(st[x][i]!=st[y][i])
x=st[x][i],y=st[y][i];
return st[x][0];
}
void work(int op){
for(int i=1;i<=n;i++)
cin>>v[i],e[i].clear();
for(int i=2,x;i<=n;i++)
cin>>x,e[x].pb(i);
dfs(1,0); buildst();
f[1]=a[1]; g[k]=a[k];
for(int i=2;i<=k;i++)
f[i]=LCA(f[i-1],a[i]);
for(int i=k-1;i>=1;i--)
g[i]=LCA(g[i+1],a[i]);
f[0]=g[2]; g[k+1]=f[k-1];
for(int i=1;i<=k;i++)
p[i][op]=v[LCA(f[i-1],g[i+1])];
}
int main(){
cin>>n>>k;
for(int i=1;i<=k;i++)
cin>>a[i];
work(0); work(1);
for(int i=1;i<=k;i++)
ans+=(p[i][0]>p[i][1]);
cout<<ans<<endl;
}
J题 Journey
题目:给你一个有向图,问能否选择一个起点,使得每个点和每条边都走且只走过一次。
思路:判断这个图是不是一条链。链的条件有一条:mn-1mn−1。这样约束起来就是树和环的组合(可能是一棵树加一个环)。再把入度和出度约束在0,1之间,这样就是链+环。然后通过入度为零的点就是起点,把整条链扫一遍,计算通过的节点个数,判断是否有环即可。
#include <bits/stdc++.h>
using namespace std;
struct inf{
public:
int u;
int v;
int cst;
};
int main(){
int n;scanf("%d",&n);
vector<vector<int>> li(n+1,vector<int>(5));
vector<vector<int>> ale(n+1,vector<int>(5));
for(int i=1;i<=n;i++)
for(int j=1;j<=4;j++)
scanf("%d",&li[i][j]);
int s1,s2,t1,t2;scanf("%d%d%d%d",&s1,&s2,&t1,&t2);
deque<inf> que;
que.push_front({s1,s2,0});
int ans=2147483647;
while(!que.empty()){
inf info=que.front();que.pop_front();
int u=info.u,v=info.v,cst=info.cst;
if(u==t1&&v==t2)ans=min(ans,cst);
int pos=0;
for(int i=1;i<=4;i++)if(li[v][i]==u)pos=i;
if(ale[v][pos]++)continue;
que.push_front({v,li[v][pos%4+1],cst});
for(int i=1;i<=4;i++){
que.push_back({v,li[v][i],cst+(i==pos%4+1?0:1)});
}
}
printf("%d",ans==2147483647?-1:ans);
}