1.CF427C Checkposts

题意:建立一些站点,如果有一个检查站在i路口,保护j的条件是:i==j或者警察巡逻车可以从i走到j,并且能回到i。求最小花费和用最少点的方案数

显然是强连通分量

在跑tarjan的过程中记录每个强连通分量中cost的最小值,在输出时遍历累乘即可

要开longlong,wa了两发

#include<bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn=3e5+5;
constexpr int mod=1e9+7;
int n,m;
int cost[maxn],dfn[maxn],low[maxn],z[maxn],tot,k,vis[maxn];
int t,scc[maxn],cnt[maxn],top,res[maxn];
vector<int>e[maxn];
vector<int>jl[maxn];
void tarjan(int u){dfn[u]=low[u]=++tot;z[++top]=u;//入栈 vis[u]=1;for(auto v:e[u]){if(!dfn[v]){tarjan(v);low[u]=min(low[u],low[v]);}else if(vis[v]){low[u]=min(low[u],dfn[v]);}}if(low[u]==dfn[u]){t++;//连通分量的标号 do{scc[z[top]]=t;    //属于这个连通分量 cnt[t]++;         //记录这个环中有多少个点res[t]=min(res[t],cost[z[top]]);jl[t].push_back(z[top]);vis[z[top]]=0; top--;              //出栈 }while(u!=z[top+1]);}
}signed main(){cin>>n;memset(res,0x3f,sizeof res);for(int i=1;i<=n;i++){cin>>cost[i];}cin>>m;for(int i=1;i<=m;i++){int u,v;cin>>u>>v;e[u].push_back(v);}for(int i=1;i<=n;i++){if(!dfn[i])tarjan(i);}int ans=0,w=1;for(int i=1;i<=t;i++){ans+=res[i];int ww=0;for(auto v:jl[i]){if(cost[v]==res[i])ww++;}w=((w*ww)%mod);//   printf("cnt = %d\n",cnt[i]);}printf("%lld %lld",ans,w);return 0;
}

2.CF1406C Link Cut Centroids

题意:给定一棵节点数为 n 的树 , 删一条边然后加上一条边 , 使得该树的重心唯一 。(删掉的边和加上的边可以是同一条)

重心最多只能有两个

如果只有一个重心,输出唯一重心上的任意一条边两次即可

如果有两个重心,把b重心的上任意一条非跟a重心相连的边连到a重心上即可

#include<bits/stdc++.h>
using namespace std;
vector<int>e[200005];
int n,m,t,maxn1,maxn2,zx1,zx2;
int d[200005];
void dfs(int s,int f){d[s]=1;int res=0;for(auto v:e[s]){if(v==f)continue;dfs(v,s);d[s]+=d[v];res=max(res,d[v]);}res=max(res,n-d[s]);if(res<maxn1){maxn1=res;zx1=s;}if(res==maxn1&&s!=zx1){maxn2=maxn1;zx2=s;}
}
int main(){cin>>t;while(t--){cin>>n;maxn1=0x3f3f3f3f,maxn2=0x3f3f3f3f+1;memset(d,0,sizeof d);for(int i=1;i<=n;i++){e[i].clear();}for(int i=1;i<=n-1;i++){int x,y;cin>>x>>y;e[x].push_back(y);e[y].push_back(x);}dfs(1,0);int f=0;if(maxn1!=maxn2){for(auto v:e[zx1]){printf("%d %d\n",zx1,v);printf("%d %d\n",zx1,v);f=1;break;}if(f)continue;}else if(maxn1==maxn2){for(auto v:e[zx2]){if(v!=zx1){printf("%d %d\n",zx2,v);printf("%d %d\n",v,zx1);f=1;break;}}}}return 0;
}

3.CF1209D Cow and Snacks

n 种花,k 个客人,每个人喜欢两种编号不同的花。但是每种花在花店里只有一束。

客人按顺序进入花店,会买走所有她喜欢且仍在店铺里的花。如果一个客人买不到任何一束花,那么她就会十分沮丧导致变成肥宅。现在你可以自己安排这 n 个人的顺序,使得肥宅的数量最小。

并查集,

#include<bits/stdc++.h>
using namespace std;
vector<int>e;
int n,m;
const int maxn=2e5+5;
int f[maxn],vis[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){int fx=find(x);int fy=find(y);f[fx]=fy;
}
int main(){cin>>n>>m;for(int i=1;i<=n;i++){f[i]=i;}for(int i=1;i<=m;i++){int x,y;cin>>x>>y;hb(x,y);}int cnt=0;for(int i=1;i<=n;i++){if(f[i]==i)cnt++;}cout<<m-n+cnt;
}

4.CF489D Unbearable Controversy of Being

题意:在一个有向图中,求类似于上图的菱形,即4个点a,b,c,da,b,c,da,b,c,d 同时存在(a,b),(a,d),(b,c),(d,c)(a,b),(a,d),(b,c),(d,c)(a,b),(a,d),(b,c),(d,c)四条边组成的菱形的个数

思路:遍历求出每个点距离为2的路径数,再用组合数 n选2

可以表示成a(a−1)2\dfrac {a(a-1)}22a(a−1)​

#include<bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn=3005,inf=0x3f3f3f3f;
constexpr int dx[]={1,-1,0,0};
constexpr int dy[]={0,0,1,-1};
int n,m,t,k;
vector<int>e[maxn];
int cnt[maxn][maxn];
signed main(){cin>>n>>m;for(int i=1;i<=m;i++){int u,v;cin>>u>>v;e[u].push_back(v);}for(int i=1;i<=n;i++){for(auto u:e[i]){for(auto v:e[u]){if(i==v)continue;cnt[i][v]++;}}}int ans=0;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){ans+=(cnt[i][j]-1)*cnt[i][j]/2;}}cout<<ans;return 0;
}

5.CF1176E Cover it!

题意:给你一张nnn个点mmm条边的无向连通图(没有边权)。保证图中没有重边和自环

你的任务是选择至多⌊n2⌋\lfloor\frac{n}{2}\rfloor⌊2n​⌋个点使得对于任意一个没有被选择的点都和至少一个选中的点相邻(换言之,通过一条边连接)

保证答案存在,如果有多个答案,输出任意一个

你将要回答多个独立的询问

思路:二分图染色
题目保证有解并且图连通,不用判断无解情况

#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=2e5+5,inf=0x3f3f3f3f;
constexpr int dx[]={1,-1,0,0};
constexpr int dy[]={0,0,1,-1};
int n,m,t,k;
vector<int>e[maxn];
int cnt,color[maxn];
inline void init(){cnt=0;for(int i=1;i<=n;i++){e[i].clear();color[i]=-1;}
}
void dfs(int u){color[u]=0;for(auto v:e[u]){if(color[v]!=-1)continue;dfs(v);if(!color[v])color[u]=1; }
}
signed main(){cin>>t;while(t--){cin>>n>>m;init();int mm=0,nb=0;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);for(int i=1;i<=n;i++){cnt+=color[i];}cout<<cnt<<endl;for(int i=1;i<=n;i++){if(color[i]){cout<<i<<" ";}}cout<<endl;}return 0;
}

6.CF1144F Graph Without Long Directed Paths

题意:给你一个无向图,把所有边标记方向,并使整张图中没有距离 >=2 的路径,问你是否存在并输出方案。

第一行输出“YES”或“NO”,若存在,第二行按照读入顺序输出连边方向

思路:二分图染色

既然距离不能达到2,那就白点向黑点连,判断有解即可

#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=2e5+5,inf=0x3f3f3f3f;
constexpr int dx[]={1,-1,0,0};
constexpr int dy[]={0,0,1,-1};
int n,m,t,k;
vector<int>e[maxn];
int cnt,color[maxn],vis[maxn];
int a[maxn],b[maxn];
void dfs(int u){vis[u]=1;for(auto v:e[u]){if(!vis[v]){color[v]=color[u]^1;dfs(v);}    else if(color[v]==color[u]){cout<<"NO";exit(0);}}
}
signed main(){cin>>n>>m;for(int i=1;i<=m;i++){int u,v;cin>>u>>v;a[i]=u;b[i]=v;e[u].push_back(v);e[v].push_back(u);}for(int i=1;i<=n;i++){if(!vis[i])dfs(i);}cout<<"YES"<<endl;for(int i=1;i<=m;i++){cout<<color[a[i]];}return 0;
}

7.CF1093D Beautiful Graph

题意:给你一个 nnn 个点 mmm 条边的无向图。

你需要给每个点一个点权,使得每条边连接的两个点点权奇偶不同。点权的值域为 {1,2,3}\{1,2,3\}{1,2,3} 。

请求出方案数对 998244353998244353998244353 取模的结果。

二分图染色,用上简单的组合,开longlong,处处求mod,一个地方不注意就炸哭了

#include<bits/stdc++.h>
using namespace std;
#define int long long
constexpr int maxn=3e5+5,inf=0x3f3f3f3f,mod=998244353;
int n,m,t;
vector<int>e[maxn];
int ans1=0,ans2=0;
int cnt,color[maxn],vis[maxn];
int flag=0;
int Pow(int x, int k){ int ans=1;for(;k;k>>=1,x=(int)x*x%mod) if(k&1) ans=(int)ans*x%mod;return ans;}
void dfs(int u,int tag){if(flag)return;if(color[u])ans1++;else ans2++;vis[u]=tag;for(auto v:e[u]){if(!vis[v]){color[v]=color[u]^1;dfs(v,tag);}else if(color[v]==color[u]){flag=1;return;}}
}
signed main(){cin>>t;while(t--){cin>>n>>m;for(int i=1;i<=n;i++){e[i].clear();vis[i]=0;color[i]=0;}flag=0;cnt=0;for(int i=1;i<=m;i++){int u,v;cin>>u>>v;e[u].push_back(v);e[v].push_back(u);}int ans=1;for(int i=1;i<=n;i++){if(!vis[i]){++cnt;ans1=0,ans2=0;dfs(i,cnt);ans=(int)ans*(Pow(2,ans1)%mod+Pow(2,ans2)%mod)%mod;}}if(flag){cout<<"0"<<endl;continue;}cout<<ans<<endl;}return 0;
}

8.CF1027D Mouse Hunt

伯兰州立大学的医学部刚刚结束了招生活动。和以往一样,约80%的申请人都是女生并且她们中的大多数人将在未来4年(真希望如此)住在大学宿舍里。

宿舍楼里有nnn个房间和一只老鼠!女孩们决定在一些房间里设置捕鼠器来除掉这只可怕的怪物。在iii号房间设置陷阱要花费cic_ici​伯兰币。房间编号从111到nnn。

要知道老鼠不是一直原地不动的,它不停地跑来跑去。如果ttt秒时它在iii号房间,那么它将在t+1t+1t+1秒时跑到aia_iai​号房间,但这期间不会跑到别的任何房间里(i=aii=a_ii=ai​表示老鼠没有离开原来的房间)。时间从000秒开始,一旦老鼠窜到了有捕鼠器的房间里,这只老鼠就会被抓住。

如果女孩们知道老鼠一开始在哪里不就很容易吗?不幸的是,情况不是这样,老鼠在第000秒时可能会在从111到nnn的任何一个房间内。

那么女孩们最少要花多少钱设置捕鼠器,才能保证老鼠无论从哪个房间开始流窜最终都会被抓到?

思路:因为有n个点n条边,所以一定会存在环,每个点只有一条出边,所以这个环一定是在链的末尾,先用拓扑排序把环外的点消去,再在森林里找到各个环内cost最小的点,相加即可

#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=2e5+5,inf=0x3f3f3f3f;
int n,m,cnt;
int du[maxn],c[maxn],vis[maxn],ans[maxn];
vector<int>e[maxn];
void topo(){queue<int>q;for(int i=1;i<=n;i++){if(du[i]==0){q.push(i);}}while(!q.empty()){int u=q.front();q.pop();for(auto v:e[u]){du[v]--;if(du[v]==0)q.push(v);}}
}
void dfs(int u,int tag){if(vis[u]||!du[u])return;vis[u]=1;ans[tag]=min(ans[tag],c[u]);for(auto v:e[u]){dfs(v,tag);}
}
int main(){cin>>n;for(int i=1;i<=n;i++){cin>>c[i];}for(int i=1;i<=n;i++){int v;cin>>v;du[v]++;e[i].push_back(v);}topo();memset(ans,inf,sizeof ans);for(int i=1;i<=n;i++){if(!vis[i]&&du[i])dfs(i,++cnt);}int res=0;for(int i=1;i<=cnt;i++){res+=ans[i];}cout<<res;
}

9.CF1320B Navigation System

给出 2≤n≤2⋅1052\le n\le2\cdot 10^52≤n≤2⋅105 个节点,2≤m≤2⋅1052\le m\le2\cdot 10^52≤m≤2⋅105 条边的有向图,路径 p1,⋯,pkp_1,\cdots,p_kp1​,⋯,pk​,路径中没有重复元素,边 (pi,pi+1)(p_i,p_{i+1})(pi​,pi+1​) 总是存在。

定义 s=p1,t=pks=p_1,t=p_ks=p1​,t=pk​ 。

有一个导航系统,若当前在节点 uuu,会构造一条从 uuu 到 ttt 的最短路径(这种路径可能不止一条,但导航系统只会选其中一条),设导航系统规划的下一个节点为 www,实际行走的下一个节点为 vvv 。

实际行走路线为 ppp,求可能的最少重构次数和最多重构次数。

思路:若当前点在最短路上,该点连边的点中,有其他点也为最短路上的点,可以选择重构,最大重构++

若当前点不在最短路上,因为必须重构,所以最大最小都++

建一个反图跑bfs,求出每一点到终点的最短路

#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=2e5+5,inf=0x3f3f3f3f;
int n,m,k,cnt;
int dis[maxn],a[maxn],vis[maxn],s,t;
vector<int>e[maxn],r[maxn];
void bfs(){dis[s]=0;queue<int>q;q.push(s);while(!q.empty()){int u=q.front();q.pop();for(auto v:r[u]){if(!dis[v]){dis[v]=dis[u]+1;q.push(v);}}}
}
int main(){cin>>n>>m;for(int i=1;i<=m;i++){int u,v;cin>>u>>v;e[u].push_back(v);r[v].push_back(u);}cin>>k;for(int i=1;i<=k;i++){cin>>a[i];}s=a[k],t=a[1];bfs();int ans1=0,ans2=0;for(int i=1;i<k;i++){if(dis[a[i]]==dis[a[i+1]]+1){for(auto v:e[a[i]]){if(v!=a[i+1]&&dis[v]==dis[a[i+1]]){ans2++;//   cout<<"!"<<endl;break;}}}else{ans1++,ans2++;}}cout<<ans1-1<<" "<<ans2-1;
}

10.CF698B Fix a Tree

题意:给出n个点的父亲,(若父亲为自己则为根节点)求出最少改掉多少个点的父亲可以使其成为一颗有根树

思路:用并查集判断树or环的个数,分两种情况:

若森林中有符合条件的树,选一个树根作为总根,将其他树or环的代表点连到根上即可输出,cnt-1

若森林中只有环,选一个环的代表点作为根,将其他的环的代表点连到根上即可,输出cnt(因为作为根的环把父节点改成了自己)

#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=2e5+5,inf=0x3f3f3f3f;
int n,m,k,cnt,root;
int f[maxn],a[maxn],vis[maxn];
vector<int>e[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){int fx=find(x);int fy=find(y);f[fx]=fy;
}
int main(){cin>>n;for(int i=1;i<=n;i++){f[i]=i;}for(int i=1;i<=n;i++){cin>>a[i];hb(i,a[i]);}for(int i=1;i<=n;i++){if(f[i]==i&&a[i]==i){root=i;}}if(root){for(int i=1;i<=n;i++){if(f[i]!=i)continue;cnt++;if(a[i]==i&&i!=root){a[i]=root;}else a[i]=root;}cout<<cnt-1<<endl;}else{for(int i=1;i<=n;i++){if(f[i]!=i)continue;cnt++;if(!root)root=i;a[i]=root;}cout<<cnt<<endl;}for(int i=1;i<=n;i++){printf("%d ",a[i]);}return 0;
}

11.CF813C The Tag Game

题意:有一颗以1为根,节点数为n的树,A在1号点,B在x号点,A,B交替行动,A的目标是行动次数尽量少,B的目标是行动次数尽量多,问在这种情况下,行动的次数.

思路:求出两个点到所有的点的最短时间,a先动,所以只要a到的时间比b要早就追不上,遍历所有点,更新最大时间即可

#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=2e5+5;
int n,m,t,k,x,cnt,nb,mm;
int dis1[maxn],dis2[maxn];
vector<int>e[maxn];
void dfs1(int u,int fa){for(auto v:e[u]){if(v==fa)continue;dis1[v]=dis1[u]+1;dfs1(v,u);}
}
void dfs2(int u,int fa){for(auto v:e[u]){if(v==fa)continue;dis2[v]=dis2[u]+1;dfs2(v,u);}
}
int main(){cin>>n>>x;for(int i=1;i<=n-1;i++){int u,v;cin>>u>>v;e[u].push_back(v);e[v].push_back(u);}dfs1(x,x);dfs2(1,1);int ans=0;for(int i=2;i<=n;i++){if(dis1[i]<dis2[i]){ans=max(ans,dis2[i]*2);}}cout<<ans;
}

12.CF229B Planets

题意:在宇宙里有 nnn 个星球,分别编号为 1,2,...,n1,2,...,n1,2,...,n 。Jack现在在 111 号星球上,他要去 nnn 号星球。已知一些星球之间有双向的传送通道,Jack可以通过这些传送通道移动。每次传送需要一些时间,在不同的星球之间传送也可能需要不同时间。

当有其他人在使用这个星球的传送通道时,Jack无法离开这个星球。比如,如果有人在 ttt 时刻使用通道,那Jack只能在 t+1t+1t+1 时刻离开(如果t+1时刻没有人在使用通道)。

现在,Jack想请你计算他最早可以在哪个时刻到达 nnn 号星球。Jack在0时刻出发。

思路:dij,到达每个点要停留一定的时间,用map保存每个点的哪个时间需要停留

#include<bits/stdc++.h>
#define int long long
using namespace std;
typedef pair<int,int>pii;
constexpr int maxn=1e5+5,inf=0x3f3f3f3f;
struct edge{int v,w;
};
vector<edge>e[maxn];
map<pair<int,int>,int>wait;
int n,m,k,t,cnt,mm,dis[maxn],vis[maxn];
bool judge(){priority_queue<pii,vector<pii>,greater<pii>>q;memset(dis,inf,sizeof dis);memset(vis,0,sizeof vis);dis[1]=0;q.push({0,1});while(!q.empty()){pii x=q.top();q.pop();int u=x.second;int w=x.first;if(vis[u])continue;vis[u]=1;while(wait[{u,w}]){w++;}for(auto ss:e[u]){int v=ss.v;if(dis[v]>w+ss.w){dis[v]=w+ss.w;q.push({dis[v],v});}}}return true;
}
signed main(){cin>>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});}for(int i=1;i<=n;i++){cin>>k;for(int j=1;j<=k;j++){int res;scanf("%lld",&res);mm=max(mm,res);wait[{i,res}]=1;}}int ans=0;bool sb=judge();ans=dis[n];if(ans<inf)cout<<ans;else cout<<-1;return 0;
}

13.CF1037D Valid BFS?

给定一个n(1≤n≤2⋅105)n(1\leq n \leq 2\cdot10^5)n(1≤n≤2⋅105)个节点的树的n−1n-1n−1条边和这棵树的一个BFSBFSBFS序a1,a2,…,ana_1,a_2,\dots,a_na1​,a2​,…,an​,判断这个BFSBFSBFS序是否是一个从节点111开始的合法BFSBFSBFS序,若合法则输出YesYesYes,否则输出NoNoNo

思路:把题目要求的bfs序列保存,对树的边进行排序,bfs序列中出现早的点排前面,再进行bfs,如果有出现点不符合该bfs序则直接跳出,否则合法

#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=2e5+5;
int n,m,k,t,cnt;
int a[maxn],b[maxn],vis[maxn];
vector<int>e[maxn];
inline void bfs(){queue<int>q;q.push(1);vis[1]=1;while(!q.empty()){int u=q.front();q.pop();if(u!=a[++cnt]){printf("No\n");exit(0);}for(auto v:e[u]){if(!vis[v]){vis[v]=1;q.push(v);}}}printf("Yes\n");
}
int main(){cin>>n;for(int i=1;i<n;i++){int u,v;cin>>u>>v;e[u].push_back(v);e[v].push_back(u);}for(int i=1;i<=n;i++){cin>>a[i];b[a[i]]=i;}for(int i=1;i<=n;i++){sort(e[i].begin(),e[i].end(),[](int x,int y){return b[x]<b[y];});}bfs();
}

14.CF1383A String Transformation 1

题意:有字符串AAA,BBB,每次在AAA中选取若干个相同的字母(设为xxx),改成另一个字母(设为yyy),需要满足x<yx<yx<y,问将A改成B的最少操作

思路:一开始看错题目了,以为要连续的…结果是任意相同的子序列就可以,直接并查集即可,相当于不同字母间连了多少次边就需要改变多少次,a->b->c->e->k,并查集合并次数即为答案

#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=2e5+5,inf=0x3f3f3f3f;
int n,m,t,k,cnt;
int f[30];
int find(int x){if(f[x]==x)return x;else return f[x]=find(f[x]);
}
void hb(int x,int y){int fx=find(x);int fy=find(y);if(fx!=fy){cnt++;f[fx]=fy;}
}
int main(){cin>>t;while(t--){cin>>n;string a1,a2;cin>>a1>>a2;for(int i=0;i<30;i++){f[i]=i;}int flag=0;for(int i=0;i<n;i++){if(a1[i]>a2[i]){flag=1;break;}else if(a1[i]!=a2[i]){hb(a1[i]-'a'+1,a2[i]-'a'+1);}}if(flag)cout<<"-1"<<endl;else cout<<cnt<<endl;cnt=0;}
}

15.CF295B Greg and Graph

Greg有一个有边权的有向图,包含nnn 个点。这个图的每两个点之间都有两个方向的边。Greg喜欢用他的图玩游戏,现在他发明了一种新游戏:

帮帮Greg,输出每一步之前要求的值。

思路:明示要用Floyd,可是又不可能每次删掉一个点再求一次,怎么办呢?这里要用逆向思维(之前kb专题有一题也是同样的思路),从后删除的边往前加边,这样就避免了每删除一次要重新计算整张图的麻烦,而且Floyd的过程跟松弛顺序是无关的,依次加入这些点,并标记为可行点,对整张图求最短路和,如果两点都为可行点则加上这两点的最短路

(题目提示了要开longlong)

#include<bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn=2e5+5,inf=0x3f3f3f3f;
int n,m,t,k,cnt,ans[maxn];
int dis[505][505],vis[505],now[505];
signed main(){cin>>n;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){cin>>dis[i][j];}}for(int i=1;i<=n;i++){cin>>vis[i];}for(int u=n;u>=1;u--){int k=vis[u];now[k]=1;for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(i==j)continue;dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]);}}for(int i=1;i<=n;i++){for(int j=1;j<=n;j++){if(i==j)continue;if(now[i]&&now[j])ans[u]+=dis[i][j];}}}for(int i=1;i<=n;i++){cout<<ans[i]<<" ";}return 0;
}

16.CF1253D Harmonious Graph

定义一张无向图是和谐的当且仅当:假设图中存在一条从 lll 到 rrr 的路径,则图中也存在从 lll 到 l+1,l+2,⋯,r−1l+1,l+2,\cdots,r-1l+1,l+2,⋯,r−1 的路径。

给出一张无向图,求至少需要添加多少条边才能将其变为和谐的。

思路:求每个联通块最大编号,若后一个联通块的最小编号小于这个联通块的最大编号,则内部一定有相交部分,需要相连,ans++

#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=2e5+5,inf=0x3f3f3f3f;
int n,m,k,t,cnt,mm;
vector<int>e[maxn];
int vis[maxn],ye[maxn];
void dfs(int u){vis[u]=1;mm=max(mm,u);for(auto v:e[u]){if(!vis[v]){dfs(v);}}
}
int main(){cin>>n>>m;for(int i=1;i<=m;i++){int u,v;cin>>u>>v;e[u].push_back(v);e[v].push_back(u);}int ans=0;for(int i=1;i<=n;i++){if(!vis[i]){if(mm>i)ans++;dfs(i);}}cout<<ans;return 0;
}

17.CF219D Choosing Capital for Treeland

题目描述

Treeland国有n个城市,这n个城市连成了一颗树,有n-1条道路连接了所有城市。每条道路只能单向通行。现在政府需要决定选择哪个城市为首都。假如城市i成为了首都,那么为了使首都能到达任意一个城市,不得不将一些道路翻转方向,记翻转道路的条数为k。你的任务是找到所有满足k最小的首都。

乍一看想到暴力搜,然而2e5的次方肯定t,然后写了一个假的dfs,去看了题解发现是换根dp,去学了一下,换根dp的思路是找一个点作为根进行一遍dfs预处理出信息,然后再在根上进行二次dfs根据公式进行递推每个节点的信息,从而避免了对每个节点都做根遍历的巨大复杂度。

回到这题,题目给的是有向边,但是用有向边是没法遍历整棵树的,所以我们先要存成无向边,加上边权,1代表是正向,0代表是反向,在第一遍dfs的统计中,如果走到的是反向边,则需要翻转,ans++。

在第二遍dfs中,每个节点需要翻转的次数可以由其父亲推导而来,画个图
1做完第一遍dfs后,f[1]=2,开始第二遍dfs
点1到点4,是正向边,f[4]=f[1]+1=3
点4到点3,是反向边,f[3]=f[4]-1=2
点4到点2,是反向边,f[2]=f[4]-1=2
所以答案是
2
1 2 3

#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=2e5+5,inf=0x3f3f3f3f;
int n,m,k,t,cnt,f[maxn];
struct edge{int v,w;
};
vector<edge>e[maxn];
int dfs(int u,int fa){int ans=0;for(auto x:e[u]){int v=x.v;int w=x.w;if(v==fa)continue;if(!w)ans++;ans+=dfs(v,u);}return ans;
}
void dfs2(int u,int fa){cnt=min(f[u],cnt);for(auto x:e[u]){int v=x.v;int w=x.w;if(v==fa)continue;f[v]=f[u]+(w==1?1:-1);dfs2(v,u);}
}
int main(){cin>>n;cnt=inf;for(int i=1;i<=n-1;i++){int u,v;cin>>u>>v;e[u].push_back((edge){v,1});e[v].push_back((edge){u,0});}f[1]=dfs(1,0);dfs2(1,0);cout<<cnt<<endl;for(int i=1;i<=n;i++){if(f[i]==cnt){printf("%d ",i);}}return 0;
}

18.咕了

19.咕了

20.咕了

Codeforce 1700Difficulty Graphs 20 questions相关推荐

  1. What are 20 questions to detect fake data scientists?

    Q1:解释什么是正规化(regularization)以及它的用处.解释特定方法的优劣势,如岭回归(ridge regression)和LASSO算法? [Matthew Mayo解答] 正则化项是保 ...

  2. codeforce golobal round 20 - 1672D - Cyclic Rotation

    1672D - Cyclic Rotation 题意:给长度相等的数组 a 和 b ,判断能否通过以下操作将 a 变为 b . 在 a 数组中一段子数组,若两端的数相同,该段向左旋转一位 分析: 想想 ...

  3. AI:Algorithmia《2020 state of enterprise machine learning—2020年企业机器学习状况》翻译与解读

    AI:Algorithmia<2020 state of enterprise machine learning-2020年企业机器学习状况>翻译与解读 目录 <2020 state ...

  4. A002-185-1203

    目录 一.查词文档 3 1.第一次查词 3 1.1需求基线(Requirements baseline) 3 1.2 概念聚类(Conceptual clustering) 7 1.3图形元素(Gra ...

  5. 本周最热 AI 论文大集合,还不快一键收藏?

    在碎片化阅读充斥眼球的时代,越来越少的人会去关注每篇论文背后的探索和思考. 在这个栏目里,你会快速 get 每篇精选论文的亮点和痛点,时刻紧跟 AI 前沿成果. 点击本文底部的「阅读原文」即刻加入社区 ...

  6. msbuild构建步骤_如何按照以下步骤构建最终的AI聊天机器人

    msbuild构建步骤 by Paul Pinard 保罗·皮纳德(Paul Pinard) 如何按照以下步骤构建最终的AI聊天机器人 (How to build the ultimate AI ch ...

  7. linux编码安装mysql_在Ubuntu 15.10下安装mysql设置数据库编码

    在从windows 10 的开发环境换到Ubuntu 15.10 后,发现原来的项目竟然不能正常地对数据库进行初始化,后来在控制台查看后,发现是数据库编码的问题. 1.在Ubuntu中安装mysql可 ...

  8. 惹怒程序员的下场!阿里达摩院大神受不了骚扰电话,业余发起“二哈”AI,315后爆红...

    李根 发自 首都机场  量子位 报道 | 公众号 QbitAI 不要惹怒程序员.不要惹怒程序员.不要惹怒程序员. 即便你是一年呼出40亿次的机器人骚扰电话. 在3.15晚会曝光机器人拨打骚扰电话黑色产 ...

  9. java编程测试题_Java编程测试可帮助您评估求职者

    java编程测试题 Sometimes back one of my good friend asked me to assess few job candidates for Java progra ...

  10. jspdf插件实现jsp页面导出为pdf文件

    最近在公司里实习作项目,项目中有一个优化需求,就是将指定的jsp页面导出为pdf文件输出.因为之前从未了解过相关方面只知识,所以在查了一番资料后,发现大家写的都很散,不是很清楚,甚至有的代码执行不出来 ...

最新文章

  1. 数组的解构赋值(未完成)
  2. java.lang.UnsupportedClassVersionError解决方案
  3. Ubuntu 16.04工具栏靠下设置
  4. 【TensorFlow】:解决TensorFlow的ImportError: DLL load failed: 动态链接库(DLL)初始化例程失败...
  5. android listview 滑动条显示_第七十六回:Android中UI控件之RecyclerView基础
  6. Java多线程系列--“JUC锁”07之 LockSupport
  7. 如何循序渐进向DotNet架构师发展(转,写的不错)
  8. 【SPSS】软件介绍
  9. 传统的 IT 销售渠道将会走向末路?
  10. python 网络调试助手
  11. 英特尔核显无法为此计算机,win10intel显卡驱动装不上怎么办_Win10系统无法安装intel显卡驱动如何解决...
  12. 什么是PoE交换机?PoE交换机与PoE+交换机的区别!
  13. 机器学习可以应用在哪些场景
  14. 密码学(五):数字签名
  15. XPath之电影天堂数据爬取
  16. 2021 - 2022个人年度总结
  17. 解决ORA-00904: invalid identifier
  18. 全面掌握前端框架Vue.js
  19. 基于GEE的制作全球任意地方时间序列数据动画的方法
  20. Spring事务的传播机制

热门文章

  1. 在MOSS2007中使用收集反馈工作流
  2. linux ftdi 虚拟,linux – 由FTDI USB串行转换器创建的监控(嗅探)/ dev / ttyUSB0
  3. python中tree安装_Python 学习笔记:Jupyter Notebook 的安装使用以及 tree 路径变更
  4. 不等式解集怎么取_6.初中数学:一个不等式的解集,都是另一个不等式的解,求a的取值范围?...
  5. python中合并字符串的库函数是_《Python Cookbook(第2版)中文版》——1.6 合并字符串...
  6. Django的数据迁移
  7. 计算机硬盘 u盘和光盘属于,磁盘U盘光盘的区别
  8. python闭包函数的必要条件_Python闭包函数
  9. python横向输出字符串_Python字符串拼接和格式化输出
  10. 链表的基本操作:创建、插入、删除操作对应c/c++代码