1.CF1328D Carousel
分类讨论:
1:为偶数,输出12121212…
2:为奇数,
但是有两个连续的图形相同,从此位置断开输出121212…
且没有任何相邻的图形相同,输出121212…3
#include<bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn=4e5+5,inf=0x3f3f3f3f,mod=1e9+7;
int n,m,t,a[maxn],res[maxn];
signed main(){
cin>>t;
while(t--){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
int flag1=0,flag2=0;
a[n+1]=a[1];
int pos;
for(int i=1;i<=n;i++){
if(a[i]==a[i+1])flag1=1,pos=i;
else flag2=1;
}
if(!flag2){
puts("1");
for(int i=1;i<=n;i++)printf("1 ");
puts("");
}
else{
if(n%2==0){
puts("2");
for(int i=1;i<=n;i++){
printf("%d ",1+(i&1));
}
puts("");
}
else if(flag1){
puts("2");
for(int i=1;i<=n;i++){
res[(pos+i-1)%n+1]=i&1;
}
for(int i=1;i<=n;i++){
printf("%d ",res[i]+1);
}
puts("");
}
else{
puts("3");
for(int i=1;i<=n-1;i++){
printf("%d ",1+(i&1));
}
puts("3");
}
}
}
}
2.CF1334D Minimum Euler Cycle
题意:求最小字典序欧拉回路的l到r个节点
经过观察可以发现
12 13 14 15 23 24 25 34 35 45 1
#include<bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn=4e5+5,inf=0x3f3f3f3f,mod=1e9+7;
int n,l,r,t;
signed main(){
cin>>t;
while(t--){
cin>>n>>l>>r;
int pos=1;
int base=0;
for(int i=(n-1)*2;i;base+=i,i-=2){
for(int j=max(base+1,l);j<=min(base+i,r);j++){
if(j%2)printf("%lld ",n-i/2);
else printf("%lld ",(j-base)/2+(n-i/2));
}
}
if(base==r-1)puts("1");
else puts("");
}
return 0;
}
3.CF1324F Maximum White Subtree
简单换根dp
#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=2e5+5,inf=0x3f3f3f3f;
int n,m,k,t,cnt,tt;
int size[maxn];
vector<int>e[maxn];
void dfs1(int u,int fa){
for(auto v:e[u]){
if(v==fa)continue;
dfs1(v,u);
if(size[v]>0)size[u]+=size[v];
}
}
void dfs2(int u,int fa){
for(auto v:e[u]){
if(v==fa)continue;
if(size[v]>0){
size[v]=max(size[v],size[u]);
}
else{
size[v]=max(size[v],size[u]+size[v]);
}
dfs2(v,u);
}
}
int main(){
cin>>n;
int flag=0;
for(int i=1;i<=n;i++){
cin>>size[i];
if(!size[i])size[i]=-1;
}
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(1,1);
dfs2(1,1);
for(int i=1;i<=n;i++){
printf("%d ",size[i]);
}
}
4.CF721C Journey
题意:给出一个
n
n
n个点
m
m
m条边的有向无环图。
问从
1
1
1到
n
n
n,在距离不超过
k
k
k的情况下最多经过多少点,并输出一个方案。
思路:spfa
#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=5005,inf=0x3f3f3f3f;
int id;
int n,m,k,mm,dis[maxn][maxn];
bool inque[maxn][maxn];
int pre[maxn][maxn];
struct edge{
int v,w;
};
vector<edge>e[maxn];
void pri(int now,int res){
if(pre[now][res]==0){
if(now==1){
printf("1 ");
}
return;
}
pri(pre[now][res],res-1);
printf("%d ",now);
}
void spfa(){
memset(dis,inf,sizeof dis);
dis[1][0]=0;
queue<pair<int,int>>q;
q.push({1,0});
while(!q.empty()){
auto x=q.front();
q.pop();
int u=x.first;
int res=x.second;
inque[u][res]=0;
for(auto y:e[u]){
int v=y.v;
int w=y.w;
if(dis[v][res+1]>dis[u][res]+w&&dis[u][res]+w<=k){
dis[v][res+1]=dis[u][res]+w;
pre[v][res+1]=u;
if(!inque[v][res+1]){
q.push({v,res+1});
inque[v][res+1]=1;
}
}
}
}
}
signed main(){
cin>>n>>m>>k;
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
e[u].push_back((edge){v,w});
}
spfa();
for(int i=n;i>=0;i--){
if(dis[n][i]<=k){
mm=i;
break;
}
}
cout<<mm+1<<endl;
pri(n,mm);
return 0;
}
5.CF404C Restore Graph
模拟
6.CF61D Eternal Victory
从根节点开始,遍历所有节点的最短路
思路:画图模拟可以发现是需要找到最长链,sum*2-最长链长度即可
#include<bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn=1e5+5,inf=0x3f3f3f3f;
typedef pair<int,int>pii;
int n,m,k,vis[maxn],dis[maxn],du[maxn];
struct edge{
int v,w;
};
vector<edge>e[maxn];
priority_queue<pii,vector<pii>,greater<pii>>q;
inline void dij(int s){
memset(dis,inf,sizeof dis);
memset(vis,0,sizeof vis);
dis[s]=0;
q.push({0,s});
while(!q.empty()){
auto x=q.top();
q.pop();
int u=x.second;
if(vis[u])continue;
vis[u]=1;
for(auto y:e[u]){
int v=y.v;
int w=y.w;
if(dis[v]>dis[u]+w){
dis[v]=dis[u]+w;
q.push({dis[v],v});
}
}
}
}
signed main(){
cin>>n;
int sum=0;
int cnt=0;
for(int i=1;i<=n-1;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});
du[u]++,du[v]++;
sum+=w;
}
dij(1);
int mm=0;
for(int i=1;i<=n;i++){
if(du[i]==1)cnt++;
}
for(int i=2;i<=n;i++){
if(du[i]==1){
mm=max(mm,dis[i]);
}
}
cout<<sum*2-mm;
}
7.CF1213G Path Queries
有一棵 n n n 个点的树,每条边都带权。
她会问你 m m m 个问题,每次给你一个正整数 q q q,求最大权值不大于 q q q 的简单路径数量。
需要注意的是,对于一个点对 ( u , v ) (u,v) (u,v) 只记一次,单独一个点不算路径。
思路:并查集,将所有询问和边权排序,累计答案输出即可
8.CF1176D Recover it!
还没写
9.CF743D Chloe and pleasant prizes
树形DP
#include<bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn=2e5+5,inf=1ll<<61;
typedef pair<int,int>pii;
int n,m,k,a[maxn],f[maxn],res[maxn],mm,ans=-inf;
int dp[maxn];
vector<int>e[maxn];
void dfs(int u,int fa){
dp[u]=-inf;
f[u]=a[u];
for(auto v:e[u]){
if(v==fa)continue;
dfs(v,u);
f[u]+=f[v];
if(dp[u]>-inf)ans=max(ans,dp[u]+dp[v]);
dp[u]=max(dp[u],dp[v]);
}
dp[u]=max(f[u],dp[u]);
}
signed main(){
cin>>n;
for(int i=1;i<=n;i++){
cin>>a[i];
}
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);
if(ans>-inf)cout<<ans;
else cout<<"Impossible";
}
10.CF1076D Edge Deletion
在最短路径树简谈中已写