- CF700B Connecting Universities
- CF1081D Maximum Distance
- CF263D Cycle in Graph
- CF645D Robot Rapping Results Report
- CF1067B Multihedgehog
- CF67A Partial Teacher
- CF638C Road Improvement
- CF20C Dijkstra?
- CF1369D TediousLee
- CF1328E Tree Queries
1.CF700B Connecting Universities
记录每条边会被多少个大学走过
#include<bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn=2e5+5,inf=0x3f3f3f3f;
vector<int>e[maxn];
int n,m,k,c[maxn],ans;
void dfs(int u,int fa){
for(auto v:e[u]){
if(v==fa)continue;
dfs(v,u);
c[u]+=c[v];
ans+=min(c[v],k-c[v]);
}
}
signed main(){
cin>>n>>k;
k*=2;
for(int i=1;i<=k;i++){
int x;
cin>>x;
c[x]=1;
}
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
}
dfs(1,1);
cout<<ans;
}
2.CF1081D Maximum Distance
连接特殊点的最长边的最小值
最小生成树中两侧都有特殊点的边的最大值
#include<bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn=2e5+5,inf=0x3f3f3f3f;
struct edge{
int u,v,w;
}e[maxn];
int n,m,k,cnt,ans;
int f[maxn],c[maxn],a[maxn];
int find(int x){
if(f[x]==x)return x;
else return f[x]=find(f[x]);
}
inline void hb(int x,int y){
a[find(y)]|=a[find(x)];
f[find(x)]=find(y);
}
inline void krus(){
sort(e+1,e+1+m,[](edge x,edge y){return x.w<y.w;});
for(int i=1;i<=m;i++){
if(find(e[i].u)==find(e[i].v))continue;
int x=find(e[i].u);
int y=find(e[i].v);
if((a[x]&1)&&(a[y]&1))ans=max(ans,e[i].w);
hb(e[i].u,e[i].v);
}
}
signed main(){
cin>>n>>m>>k;
for(int i=1;i<=k;i++){
int x;
cin>>x;
a[x]=1;
}
for(int i=1;i<=n;i++){
f[i]=i;
}
for(int i=1;i<=m;i++){
int u,v,w;
cin>>e[i].u>>e[i].v>>e[i].w;
}
krus();
for(int i=1;i<=k;i++){
cout<<ans<<" ";
}
return 0;
}
3.CF263D Cycle in Graph
dfs过程中给每个点打上时间戳,若时间戳之差大于等于k,则找到了题目要求的环,标记环的起点并输出答案即可
#include<bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn=2e5+5,inf=0x3f3f3f3f;
vector<int>e[maxn];
int n,m,k;
int vis[maxn],pos;
void dfs(int u,int tim){
vis[u]=tim;
for(auto v:e[u]){
if(!vis[v]){
dfs(v,tim+1);
break;
}
if(vis[u]>=vis[v]+k){
cout<<vis[u]-vis[v]+1<<endl;
cout<<u<<" ";
pos=v;
return;
}
}
if(pos!=-1)cout<<u<<" ";
if(pos==u)pos=-1;
}
signed main(){
cin>>n>>m>>k;
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
}
dfs(1,1);
}
4.CF645D Robot Rapping Results Report
二分需要的边数,拓扑排序
#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=1e5+5,inf=0x3f3f3f3f;
vector<int>e[maxn];
int n,m,cnt;
int a[maxn],b[maxn],du[maxn],vis[maxn];
bool topo(int x){
queue<int>q;
memset(du,0,sizeof du);
memset(vis,0,sizeof vis);
for(int i=1;i<=x;i++){
e[i].clear();
}
int cnt=0;
for(int i=1;i<=x;i++){
int u=a[i];
int v=b[i];
du[v]++;
e[u].push_back(v);
if(!vis[u])vis[u]++,cnt++;
if(!vis[v])vis[v]++,cnt++;
}
int flag=0;
if(cnt<n)return false;
for(int i=1;i<=n;i++){
if(!du[i])q.push(i);
}
if(q.size()>=2){
return false;
}
while(!q.empty()){
int u=q.front();
q.pop();
for(auto v:e[u]){
du[v]--;
if(!du[v])q.push(v);
}
if(q.size()>=2){
flag=1;
break;
}
}
if(flag)return false;
return true;
}
int main(){
cin>>n>>m;
for(int i=1;i<=m;i++){
cin>>a[i]>>b[i];
}
int l=1,r=m;
int ans=-1;
while(l<=r){
int mid=(l+r)/2;
if(topo(mid))ans=mid,r=mid-1;
else l=mid+1;
}
cout<<ans;
}
5.CF1067B Multihedgehog
从外圈向内bfs,如果外圈有跟外圈相连的边,no,如果有内圈的点度数不足3,no
#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=1e5+5,inf=0x3f3f3f3f;
vector<int>e[maxn];
int n,m,cnt,k,res=-1;
int a[maxn],du[maxn];
inline void solve(){
queue<int>q;
for(int i=1;i<=n;i++){
if(e[i].size()==1){
q.push(i);
a[i]=2;
du[i]=1;
}
}
int sz=q.size();
int dd=0;
while(!q.empty()){
int u=q.front();
q.pop();
sz--;
for(auto v:e[u]){
if(!du[v]){
q.push(v);
a[v]=1;
}
else if(a[v]==2){
cout<<"No";
exit(0);
}
du[v]++;
}
if(!sz){
sz=q.size();
res++;
if(sz)dd=sz;
for(int i=1;i<=n;i++){
if(a[i]==2)a[i]=0;
if(a[i]==1&&du[i]<3){
cout<<"No";
exit(0);
}
a[i]*=2;
}
}
}
if(res==k&&dd==1){
cout<<"Yes";
return;
}
else cout<<"No";
}
int main(){
cin>>n>>k;
for(int i=1;i<=n-1;i++){
int u,v;
cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
}
solve();
return 0;
}
6.CF67A Partial Teacher
差分约束板子
#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=1e5+5,inf=0x3f3f3f3f;
int n,m,cnt,k,res=-1;
int dis[maxn],inque[maxn];
struct edge{
int v,w;
};
vector<edge>e[maxn];
inline void add(int u,int v,int w){
e[u].push_back((edge){v,w});
}
inline void spfa(){
memset(dis,-inf,sizeof dis);
dis[0]=0;
queue<int>q;
q.push(0);
while(!q.empty()){
int u=q.front();
q.pop();
inque[u]=0;
for(auto x:e[u]){
int v=x.v;
int w=x.w;
if(dis[v]<dis[u]+w){
dis[v]=dis[u]+w;
if(!inque[v]){
inque[v]=1;
q.push(v);
}
}
}
}
}
int main(){
cin>>n;
for (int i=1;i<n;i++){
char ch=' ';
while(ch!='R'&&ch!='L'&&ch!='=')ch=getchar();
if (ch=='L') add(i+1,i,1);
if (ch=='R') add(i,i+1,1);
if (ch=='=') add(i+1,i,0), add(i,i+1,0);
}
for(int i=1;i<=n;i++){
add(0,i,1);
}
spfa();
for(int i=1;i<=n;i++){
cout<<dis[i]<<" ";
}
return 0;
}
7.CF638C Road Improvement
#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=2e5+5,inf=0x3f3f3f3f;
int n,m,cnt=1;
int head[maxn],col[maxn],du[maxn];
int k;
struct edge{
int u,v,nex;
}e[maxn*2];
vector<int>d[maxn];
inline void add(int u,int v){
e[++cnt].v=v;
e[cnt].u=u;
e[cnt].nex=head[u];
head[u]=cnt;
}
void dfs(int u,int fa){
int id=1;
for(int i=head[u];i;i=e[i].nex){
int v=e[i].v;
if(v==fa)continue;
if(col[u]==id)id++;
col[v]=id;
d[id].push_back(i/2);
k=max(k,id);
id++;
dfs(v,u);
}
}
int main(){
cin>>n;
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
add(u,v);
add(v,u);
}
dfs(1,1);
cout<<k<<endl;
for(int i=1;i<=k;i++){
cout<<d[i].size()<<" ";
for(auto x:d[i]){
cout<<x<<" ";
}
puts("");
}
return 0;
}
8.CF20C Dijkstra?
最短路记录路径模板
#include<bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn=2e5+5;
constexpr int inf=0x3f3f3f3f3f3f3f3f;
typedef pair<int,int>pii;
int cnt,n,m,s,vis[maxn],dis[maxn],pre[maxn];
struct edge{
int v,w;
};
vector<edge>e[maxn];
priority_queue<pii,vector<pii>,greater<pii>>q;
inline void dij(int s){
for(int i=0;i<=n;i++){
dis[i]=inf;
vis[i]=0;
}
dis[1]=0;
q.push({0,1});
while(!q.empty()){
pii x=q.top();
q.pop();
int u=x.second;
if(vis[u])continue;
vis[u]=1;
for(auto ss:e[u]){
int v=ss.v;
if(dis[v]>dis[u]+ss.w){
dis[v]=dis[u]+ss.w;
pre[v]=u;
q.push({dis[v],v});
}
}
}
}
void dfs(int u){
if(pre[u])dfs(pre[u]);
printf("%lld ",u);
}
signed main(){
scanf("%lld%lld",&n,&m);
for(int i=1;i<=m;i++){
int u,v,w;
scanf("%lld%lld%lld",&u,&v,&w);
e[u].push_back((edge){v,w});
e[v].push_back((edge){u,w});
}
dij(1);
/* for(int i=1;i<=n;i++){
printf("%lld\n",dis[i]);
}*/
if(dis[n]==inf)puts("-1");
else{
dfs(n);
}
return 0;
}
9.CF1369D TediousLee
推公式,最下面一层能有多少个claw取决于上一层有多少个1个儿子的点,两层前的答案不会影响到后面,直接累加即可
#include<bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn=2e6+5,inf=0x3f3f3f3f,mod=1e9+7;
int n,m,t,res[maxn];
int a[maxn],b[maxn];
void pre(){
for(int i=3;i<maxn-2;i++){
a[i]=b[i-1]%mod;
b[i]=(b[i-1]+a[i-1]*2)%mod;
res[i]=(res[i-3]+a[i-1])%mod;
}
}
signed main(){
a[2]=1;
b[2]=1;
pre();
cin>>t;
while(t--){
scanf("%lld",&n);
printf("%lld\n",4*res[n]%mod);
}
return 0;
}
10.CF1328E Tree Queries
利用父亲节点的dfs序和子树大小,判断相邻两个节点,dfn序大的是否在dfn序小的点的子树里
#include<bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn=2e5+5,inf=0x3f3f3f3f,mod=1e9+7;
vector<int>e[maxn];
int n,m,t,res[maxn];
int sz[maxn],dfn[maxn],f[maxn];
int tot;
void dfs(int u,int fa){
dfn[u]=++tot;
f[u]=fa;
sz[u]=1;
for(auto v:e[u]){
if(v==fa)continue;
dfs(v,u);
sz[u]+=sz[v];
}
}
signed main(){
int q;
cin>>n>>q;
for(int i=1;i<n;i++){
int u,v;
cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
}
dfs(1,1);
for(int i=1;i<=q;i++){
int k;
cin>>k;
vector<pair<int,int>>w;
for(int j=1;j<=k;j++){
int x;
cin>>x;
w.push_back({dfn[f[x]],f[x]});
}
sort(w.begin(),w.end());
int flag=0;
for(int j=0;j<k-1;j++){
if(w[j].first+sz[w[j].second]>w[j+1].first)continue;
flag=1;
}
if(flag)puts("NO");
else puts("YES");
}
return 0;
}