1.CF1187E Tree Painting
题目:
给定一棵n个点的树 初始全是白点
要求你做n步操作,每一次选定一个与一个黑点相隔一条边的白点,将它染成黑点,然后获得该白点被染色前所在的白色联通块大小的权值。
第一次操作可以任意选点。
求可获得的最大权值
思路:换根dp
s o n [ i ] son[i] son[i]表示第 i i i个点这棵树的大小, f [ i ] f[i] f[i]代表以 i i i点为根子树的答案
每个点获得的价值= s o n [ i ] son[i] son[i]+所有子树的 f f f
开始换根
f
[
1
]
=
s
o
n
[
1
]
+
f
[
2
]
+
f
[
4
]
f[1]=son[1]+f[2]+f[4]
f[1]=son[1]+f[2]+f[4]
f
[
4
]
=
s
o
n
[
4
]
+
f
[
9
]
f[4]=son[4]+f[9]
f[4]=son[4]+f[9]
n
e
w
new
new
f
1
=
n
e
w
f1 = new
f1=new
s
o
n
1
son1
son1+
f
[
2
]
f[2]
f[2]
n
e
w
new
new
s
o
n
1
=
s
o
n
[
1
]
−
s
o
n
[
4
]
son1 = son[1]-son[4]
son1=son[1]−son[4]
n
e
w
new
new
f
4
f4
f4
=
=
=
n
e
w
new
new
s
o
n
4
+
n
e
w
son4 +new
son4+new
f
1
f1
f1 +
f
[
9
]
f[9]
f[9]
n
e
w
new
new
s
o
n
4
=
son4 =
son4=
s
o
n
[
1
]
son[1]
son[1]
s
o
n
[
1
]
=
n
son[1]=n
son[1]=n
经过愉快的代换后,我们就能得到 n e w new new f 4 f4 f4 = = = f [ 1 ] f[1] f[1]+ n − 2 ∗ s o n [ 4 ] n-2*son[4] n−2∗son[4]
就可以写出最终答案啦:
(第10086次心碎教训告诉我要记得开longlong)
#include<bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn=4e5+5;
int n,son[maxn],f[maxn],ans;
vector<int>e[maxn];
void dfs1(int u,int fa){
son[u]=1;
for(auto v:e[u]){
if(v==fa)continue;
dfs1(v,u);
son[u]+=son[v];
f[u]+=f[v];
}
f[u]+=son[u];
}
void dfs2(int u,int fa){
ans=max(ans,f[u]);
for(auto v:e[u]){
if(v==fa)continue;
f[v]=f[u]+n-2*son[v];
ans=max(f[v],ans);
dfs2(v,u);
}
}
signed main(){
cin>>n;
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);
cout<<ans;
}
2.CF796D Police Stations
题意:给定一棵树,树上有一些点是警察局,要求所有点到最近的警察局的距离不大于d,求最多能删几条边
思路:bfs
一开始把所有的警察局点加入队列进行bfs,记录每个点所属的警察局,如果边相连的两个点不属于同一个警察局则可删除
坑点:一个点可能有多个警察局,要判重(写程序10分钟debug半小时默默流泪)
#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=3e5+5,inf=0x3f3f3f3f;
struct bb{
int u,v;
}sb[maxn];
struct edge{
int v,id;
};
vector<edge>e[maxn];
int f[maxn],vis[maxn],dis[maxn],a[maxn],fw[maxn];
int n,m,k,d,cnt,ans;
struct node{
int v,fa,color,dis;
};
vector<int>jl;
void bfs(){
queue<node>q;
memset(dis,inf,sizeof dis);
for(int i=1;i<=cnt;i++){
q.push((node){a[i],a[i],i,0});
fw[a[i]]=i;
}
while(!q.empty()){
auto tt=q.front();
q.pop();
int u=tt.v;
int fa=tt.fa;
int col=tt.color;
int dis=tt.dis;
if(dis==d)continue;
for(auto x:e[u]){
int v=x.v;
if(fw[v])continue;
fw[v]=col;
q.push((node){v,fa,col,dis+1});
}
}
}
int main(){
cin>>n>>k>>d;
for(int i=1;i<=k;i++){
int x;
cin>>x;
if(!f[x]){
f[x]=1;
a[++cnt]=x;
}
}
for(int i=1;i<=n-1;i++){
int u,v;
cin>>u>>v;
sb[i].u=u;
sb[i].v=v;
e[u].push_back((edge){v,i});
e[v].push_back((edge){u,i});
}
bfs();
for(int i=1;i<=n-1;i++){
if(fw[sb[i].u]!=fw[sb[i].v]){
// printf("%d ",res);
ans++;
}
}
cout<<ans<<endl;
int res=0;
for(int i=1;i<=n-1;i++){
if(fw[sb[i].u]!=fw[sb[i].v]){
printf("%d ",i);
ans++;
}
}
}
3.CF909E Coprocessor
题意:有一堆任务,构成一个DAG,有的任务只能用主处理器完成,有的任务只能用副处理器完成,但是副处理器一次能完成当前一堆需要副处理器完成的任务,问遍历完整张图最少需要用多少次副处理器
思路:拓扑排序,贪心
只要当前还有点能用主处理器完成就将其加入队列继续拓扑,直到当前剩下的都得用副处理器,然后一次性处理完所有需要用副处理器的任务
#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=1e5+5,inf=0x3f3f3f3f;
vector<int>e[maxn];
int f[maxn],n,m,cnt,ans,du[maxn];
void topo(){
queue<int>q1,q2;
for(int i=1;i<=n;i++){
if(du[i]==0&&f[i]==0)q1.push(i);
if(du[i]==0&&f[i]==1)q2.push(i);
}
while(q1.size()||q2.size()){
while(!q1.empty()){
int u=q1.front();
q1.pop();
for(auto v:e[u]){
du[v]--;
if(!du[v]){
if(!f[v])q1.push(v);
else q2.push(v);
}
}
}
if(q2.size())ans++;
while(!q2.empty()){
int u=q2.front();
q2.pop();
for(auto v:e[u]){
du[v]--;
if(!du[v]){
if(!f[v])q1.push(v);
else q2.push(v);
}
}
}
}
}
int main(){
cin>>n>>m;
for(int i=1;i<=n;i++){
cin>>f[i];
}
for(int i=1;i<=m;i++){
int u,v;
cin>>v>>u;
u++;
v++;
e[u].push_back(v);
du[v]++;
}
topo();
cout<<ans;
}
4.CF746G New Roads
#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=2e5+5,inf=0x3f3f3f3f;
vector<int>e[maxn];
int n,m,t,k,a[maxn],f[maxn],cnt;
int main(){
cin>>n>>t>>k;
a[0]=1;
for(int i=1;i<=t;i++){
cin>>a[i];
}
if(a[t]>k||n-t<k){
puts("-1");
return 0;
}
for(int i=0;i<=t;i++){
for(int j=1;j<=a[i];j++){
e[i].push_back(++cnt);
}
}
for(int i=0;i<a[1];i++){
f[e[1][i]]=1;
}
for(int i=2;i<=t;i++){
f[e[i][0]]=e[i-1][0];
}
int res=n-k-t;
for(int i=2;i<=t;i++){
for(int j=1;j<a[i];j++){
if(res&&j<a[i-1]){
f[e[i][j]]=e[i-1][j];
res--;
}
else f[e[i][j]]=e[i-1][0];
}
}
if(res){
puts("-1");
return 0;
}
cout<<n<<endl;
for(int i=2;i<=n;i++){
printf("%d %d\n",i,f[i]);
}
return 0;
}
5.CF243B Hydra
#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=1e5+5,inf=0x3f3f3f3f;
vector<int>e[maxn],ans;
int n,m,t,h,k,tim,du[maxn],cnt,c[maxn],vis[maxn];
int main(){
cin>>n>>m>>h>>t;
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
e[u].push_back(v);
e[v].push_back(u);
du[u]++,du[v]++;
}
for(int i=1;i<=m;i++){
if(du[i]<=h)continue;
for(auto j:e[i])c[j]=i;
for(auto j:e[i]){
tim++;
int p=du[i]-1-h,q=0;
ans.clear();
for(auto k:e[j]){
if(k!=i){
if(c[k]==i&&p){
p--;
q++;
vis[k]=tim;
ans.push_back(k);
}
else if(c[k]!=i){
q++;
vis[k]=tim;
ans.push_back(k);
}
}
if(q==t)break;
}
if(q==t){
int res=0;
puts("YES");
printf("%d %d\n",i,j);
for(int k:e[i]){
if(k!=j&&vis[k]!=tim){
printf("%d ",k);
res++;
}
if(res==h)break;
}
puts("");
for(auto x:ans){
printf("%d ",x);
}
return 0;
}
}
}
puts("NO");
}
6.CF59E Shortest Path
#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=3005,maxm=4e5+5,inf=0x3f3f3f3f;
vector<int>mp[maxn][maxn];
struct edge{
int v,nex;
}e[maxm];
int n,m,k,t,cnt=1,pre[maxm],vis[maxm],dis[maxm];
int head[maxm];
bool judge(int x,int y,int z){
for(auto t:mp[x][y]){
if(t==z)return true;
}
return false;
}
void add(int u,int v){
e[++cnt].v=v;
e[cnt].nex=head[u];
head[u]=cnt;
}
void pri(int i){
if(i){
pri(pre[i]);
printf("%d ",e[i].v);
}
else printf("1 ");
}
bool bfs(){
queue<pair<int,int>>q;
dis[1]=0;
q.push({1,0});
while(!q.empty()){
auto x=q.front();
q.pop();
int u=x.first;
int id=x.second;
for(int i=head[u];i;i=e[i].nex){
int v=e[i].v;
int qq=e[id^1].v;
if(vis[i]||judge(qq,u,v))continue;
dis[i]=dis[id]+1;
pre[i]=id;
vis[i]=1;
if(v==n){
printf("%d\n",dis[i]);
pri(i);
return true;
}
q.push({v,i});
}
}
return false;
}
int main(){
cin>>n>>m>>k;
for(int i=1;i<=m;i++){
int u,v;
cin>>u>>v;
add(u,v);
add(v,u);
}
for(int i=1;i<=k;i++){
int x,y,z;
cin>>x>>y>>z;
mp[x][y].push_back(z);
}
if(!bfs())puts("-1");
}
7.CF237E Build String
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
const int inf=0x3f3f3f3f,maxn=505,maxm=10005;
struct edge{
int nex,v,cost,flow;
}e[maxm];
int head[maxn],cnt=1;
int n,m,k,T,w[maxn];
string s,p;
int a[maxn][maxn],b[maxn];
inline void add_edge(int u,int v,int cost,int flow){
e[++cnt].v=v;
e[cnt].cost=cost;
e[cnt].flow=flow;
e[cnt].nex=head[u];
head[u]=cnt;
e[++cnt].v=u;
e[cnt].cost=-cost;
e[cnt].flow=0;
e[cnt].nex=head[v];
head[v]=cnt;
}
int inque[maxn],dis[maxn],flow[maxn],pre[maxn],last[maxn];
bool spfa(int s,int t){
queue<int>q;
memset(dis,0x3f,sizeof dis);
memset(flow,0x3f,sizeof flow);
memset(inque,0,sizeof inque);
q.push(s);
inque[s]=1;
dis[s]=0;
pre[t]=-1;
while(!q.empty()){
int u=q.front();
q.pop();
inque[u]=0;
for(int i=head[u];i;i=e[i].nex){
int v=e[i].v;
if(dis[v]>dis[u]+e[i].cost&&e[i].flow){
dis[v]=dis[u]+e[i].cost;
pre[v]=u;
last[v]=i;
flow[v]=min(flow[u],e[i].flow);
if(!inque[v]){
q.push(v);
inque[v]=1;
}
}
}
}
if(pre[t]!=-1)return true;
return false;
}
inline pair<int,int> mcmf(int s,int t){
int maxflow=0;
int mincost=0;
while(spfa(s,t)){
int u=t;
maxflow+=flow[t];
mincost+=flow[t]*dis[t];
while(u!=s){
e[last[u]].flow-=flow[t];
e[last[u]^1].flow+=flow[t];
u=pre[u];
}
}
return {maxflow,mincost};
}
int main(){
cin>>p;
cin>>n;
int st=502;
int ed=503;
for(int i=1;i<=n;i++){
cin>>s>>w[i];
for(auto x:s){
a[i][x-'a'+1]++;
}
add_edge(st,i,0,w[i]);
}//s到n个串
for(auto x:p){
b[x-'a'+1]++;
}//p串
for(int i=1;i<=n;i++){
for(int j=1;j<=26;j++){
if(a[i][j]){
add_edge(i,n+j,i,a[i][j]);
}
}
}
for(int i=1;i<=26;i++){
if(b[i]){
add_edge(n+i,ed,0,b[i]);
}
}
auto x=mcmf(st,ed);
if(x.first==p.length())cout<<x.second;
else cout<<-1;
}
8.CF793D Presents in Bankopolis
#include<bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
constexpr int inf=0x3f3f3f3f,maxn=85;
int f[maxn][maxn][maxn][2];
int n,m,k,ans=inf;
struct edge{
int v,w;
};
vector<edge>e[maxn];
int find(int l,int r,int res,int col){
if(f[l][r][res][col]!=-1)return f[l][r][res][col];
if(res==0)return f[l][r][res][col]=0;
int u=(col==0?l:r);
int qq=inf;
for(auto x:e[u]){
int v=x.v;
int w=x.w;
if(v>l&&v<r)qq=min(qq,min(find(l,v,res-1,1),find(v,r,res-1,0))+w);
}
return f[l][r][res][col]=qq;
}
int main(){
cin>>n>>k>>m;
for(int i=1;i<=m;i++){
int u,v,w;
cin>>u>>v>>w;
e[u].push_back((edge){v,w});
}
memset(f,-1,sizeof f);
for(int i=1;i<=n;i++){
ans=min({ans,find(0,i,k-1,1),find(i,n+1,k-1,0)});
}
if(ans==inf)puts("-1");
else cout<<ans;
return 0;
}
写完了没保存刷新了没了,自闭了,不写了
9.CF803E Roma and Poker
题意:给定一个由
W
,
D
,
L
,
?
W,D,L,?
W,D,L,? 构成的长度为
n
n
n 的字符串,并给定一个常数
k
k
k ,你要替换字符串中的所有
?
?
? ,使得原串的
W
,
L
W,L
W,L 出现次数之差的绝对值
=
k
=k
=k ,且除原串外任意前缀的
W
,
L
W,L
W,L 出现次数之差的绝对值
k
k
k ,求构造出的字符串,无解输出 NO
,否则输出构造后的字符串。
思路:记忆化搜索
#include<bits/stdc++.h>
using namespace std;
constexpr int maxn=1005,inf=0x3f3f3f3f;
string s;
long long n,m,k;
bool f[1005][1005];
bool dfs(int now,int x){
if(now==n&&abs(x)==k)return 1;
if(now==n||abs(x)>=k)return 0;
if(f[now][x])return 0;
f[now][x]=1;
if(s[now]=='W')return dfs(now+1,x+1);
if(s[now]=='D')return dfs(now+1,x);
if(s[now]=='L')return dfs(now+1,x-1);
if(dfs(now+1,x+1)){
s[now]='W';
return 1;
}
if(dfs(now+1,x )){
s[now]='D';
return 1;
}
if(dfs(now+1,x-1)){
s[now]='L';
return 1;
}
}
int main(){
cin>>n>>k;
cin>>s;
if(dfs(0,0))cout<<s;
else cout<<"NO";
}
10.CF859E Desk Disorder
题意:有
N
N
N 个人和
2
N
2N
2N 个座位。告诉你这
N
N
N 个人它们现在的座位。以及它们想去的座位。
每个人可以去它们想去的座位或者就坐在原来的座位上。
新的座位安排和旧的座位安排,都不允许一个座位被两个人占据的情况。
问你新的座位安排的方案数。
思路:并查集,分类讨论
只有三种情况:
1.树
2.环or基环树
3.自环
用并查集维护,如果当前子图有自环的环无论如何都不能动,方案为1,如果是树方案数为树的节点数,如果是环or基环树,方案数为2(只有环上的可以动)
最后相乘即可
#include<bits/stdc++.h>
#define int long long
using namespace std;
constexpr int maxn=2e5+5,inf=0x3f3f3f3f,mod=1e9+7;
int f[maxn],n,m,s[maxn],c[maxn],ans=1,h[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);
if(fx!=fy){
h[fy]|=h[fx];
s[fy]+=s[fx];
c[fy]+=c[fx]+1;
f[fx]=fy;
}
else if(fx==fy){
c[fy]++;
}
}
signed main(){
cin>>n;
for(int i=1;i<=2*n;i++){
f[i]=i;
s[i]=1;
}
for(int i=1;i<=n;i++){
int u,v;
cin>>u>>v;
if(u==v)h[u]=h[v]=1;
hb(u,v);
}
for(int i=1;i<=2*n;i++){
if(f[i]==i&&s[i]!=1&&!h[i]){
if(s[i]==c[i]){
ans=ans*2%mod;
}
else if(s[i]==c[i]+1){
ans=ans*s[i]%mod;
}
}
}
cout<<ans%mod;
}