写这几个题解我觉得我就像在按照官方题解抄一样

阴阳

题解

将题目中给的阴阳看作黑色和白色

首先我们观察到最后生成图中某种颜色必须是竖着单调递增或竖着单调递减

类似这样

否则不满足这个条件

但合法染色方案必须满足任意两个同颜色格子之间的格子也必须是该颜色。

然后我们分四种情况统计,

1.黑色居于左侧而且分界点单调不降,

2.黑色居于左侧而且分界点单调不升,

3.白色居于左侧而且分界点单调不降,

4.白色居于左侧而且分界点单调不升。

我们发现这样会算重,

dp然后手动容斥,

1,2会算重左面每列全是黑色

类似于

类似的3,4会算重左面全是白色

那么上面全是黑色我们也会算重(2,3)

上面全是白色我们仍然会算重

手动容斥

题解应该都能看懂,实现稍难(不用说了我码力太弱)

代码

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define A 1111
const ll mod=1e9+7;
ll can[A][A][10],f[A][A][2],up[A][A],down[A][A];
//can定义为i行从1--j染成B剩下染成W是否合法
char ch[A][A];
ll n,m,flag1,flag2,ans;
int main(){
scanf("%lld%lld",&n,&m);
for(ll i=1;i<=n;i++)
scanf("%s",ch[i]+1);
for(ll i=1;i<=n;i++){
ll maxpos=0;
for(ll j=1;j<=m;j++){
if(ch[i][j]=='W') break;
if(ch[i][j]=='B') maxpos=j;
}
for(ll j=maxpos+1;j<=m;j++)
if(ch[i][j]=='B'){
maxpos=m+1; break;
}
ll now=maxpos;
while(ch[i][now]!='W'&&now<=m)
can[i][now][1]=1,now++;
} for(ll i=1;i<=n;i++){
ll maxpos=m+1;
for(ll j=m;j>=1;j--){
if(ch[i][j]=='W') break;
if(ch[i][j]=='B') maxpos=j;
}
for(ll j=maxpos-1;j>=1;j--)
if(ch[i][j]=='B'){
maxpos=-1; break;
}
ll now=maxpos;
while(ch[i][now]!='W'&&now>=0)
can[i][m-now+1][2]=1,now--;
}
for(ll i=0;i<=m;i++)
up[0][i]=1,down[0][i]=1;
for(ll i=1;i<=n;i++){
for(ll j=0;j<=m;j++){
if(!can[i][j][1]) continue;
f[i][j][0]=up[i-1][j];
f[i][j][1]=down[i-1][j];
// printf("up[%lld][%lld]=%lld down=%lld\n",i-1,j,up[i-1][j],down[i-1][j]);
}
for(ll j=0;j<=m;j++)
up[i][j]=(up[i][j-1]+f[i][j][0])%mod/*,printf("f=%lld up=%lld\n",f[i][j][0],up[i][j])*/;
for(ll j=m;j>=0;j--)
down[i][j]=(down[i][j+1]+f[i][j][1])%mod;
// printf("up=%lld down=%lld\n",up[n][m],down[n][0]);
}
/* for(ll i=1;i<=n;i++,puts("")){
for(ll j=1;j<=m;j++){
printf("%lld ",can[i][j][1]);
}
}
*/ memset(f,0,sizeof(f));
ans=(ans+up[n][m]+down[n][0]+mod)%mod;
// printf("ans=%lld\n",ans);
for(ll i=1;i<=n;i++){
for(ll j=0;j<=m;j++){
if(!can[i][j][2]) continue;
f[i][j][0]=up[i-1][j];
f[i][j][1]=down[i-1][j];
}
for(ll j=0;j<=m;j++)
up[i][j]=(up[i][j-1]+f[i][j][0])%mod;
for(ll j=m;j>=0;j--)
down[i][j]=(down[i][j+1]+f[i][j][1])%mod;
}
// printf("up=%lld down=%lld\n",up[n][m],down[n][0]);
ans=(ans+up[n][m]+down[n][0]+mod)%mod;
// printf("ans=%lld\n",ans);
memset(f,0,sizeof(f));
//减去左右重复
for(ll i=1;i<m;i++){
ll flag=0;
for(ll j=1;j<=n;j++)
if(!can[j][i][1]){
flag=1;break;
}
if(!flag) ans--;
}
for(ll i=1;i<m;i++){
ll flag=0;
for(ll j=1;j<=n;j++)
if(!can[j][i][2]){
flag=1;break;
}
if(!flag) ans--;
}
//减去上下
//若上面为B下面只能为W
for(ll i=1;i<n;i++){
ll flag=0;
for(ll j=1;j<=i;j++)
if(!can[j][m][1]){
flag=1;break;
}
for(ll j=i+1;j<=n;j++)
if(!can[j][0][1]){
flag=1;break;
}
if(flag)continue;
ans--;
}
for(ll i=n;i>=2;i--){
ll flag=0;
for(ll j=1;j<=i-1;j++)
if(!can[j][0][1]){
flag=1;break;
}
for(ll j=i;j<=n;j++)
if(!can[j][m][1]){
flag=1;break;
}
if(flag)continue;
ans--;
}
for(ll i=1;i<=n;i++){
if(!can[i][0][1]) flag1=1;
if(!can[i][m][1]) flag2=1;
}
if(!flag1) ans-=3;
if(!flag2) ans-=3;
printf("%lld\n",(ans+mod)%mod);
}

题解

我们发现一条性质我们子树内两个点要变成黑色我们同时经过树外的边不会使次数变优(除了直接与lca相连的边)

然后根据这条性质,我们发现我们一定存在一种最优方案使任意两条染色路径互不相交

然后我们进行贪心

首先题目中给的无要求的边我们进行缩边

我们统计到当前子树都已经全部染成黑色了,那么我们只用考虑与它相连就行

拿下面这个图举例(假设全部为白边)

你考虑3时你6的子树都处理完了,然后你遇到两个白色边(3,6)(3,7)你贪心直接染色就行,那么如果最后剩下一个没有染色怎么办,显然我们不用管,我们发现与3相连的边(1,3)这条边是必定被染色的,2本来要和3进行染色让(1,2)(1,3)进行染色,我们现在把这个边拉过来变成(2,8)进行染色就行了

那么依据上文说的,我们只需要让与3相连白边个数(除了父亲与它相连边)/2就行了

推广到所有点统计白边个数/2即可

然后这样做对于根来说会出错,特判一下就AC了(对于根来说没有办法再让自己父亲拉边过来)

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#include<algorithm>
using namespace std;
#define R register
#define ll long long
inline ll read()//-------
{
ll aa=0;char cc=getchar();
while(cc<'0'||cc>'9') cc=getchar();
while(cc<='9'&&cc>='0')
{aa=(aa<<3)+(aa<<1)+(cc^48);cc=getchar();}
return aa;
}
const int N=1000005;
struct tree{
int v,last;
}tr[N<<1];
int tot,first[N];
inline void add(int x,int y)
{
tr[++tot]=(tree){y,first[x]};
first[x]=tot;return;
}
int n,ans,mp[N],vi[N];
int dfs(int x,int fa)
{
int sum=0;vi[x]=1;
for(R int i=first[x],v;i;i=tr[i].last){
v=tr[i].v;
if(v==fa)continue;
dfs(v,x);
sum^=1;
if(!sum)++ans;
}
return sum;
}
int main()
{
//freopen("tight.in","r",stdin);
//freopen("tight.out","w",stdout);
n=read();mp[1]=++mp[0];
for(R int i=2,x,y,z;i<=n;++i){
x=read();y=read();z=read();
if(!z){
if(mp[i])mp[x]=mp[i];
else if(mp[x])mp[i]=mp[x];
else mp[i]=mp[x]=++mp[0];
continue;
}
if(!mp[i])mp[i]=++mp[0];
if(!mp[x])mp[x]=++mp[0];
if(y)continue;
add(mp[i],mp[x]);
add(mp[x],mp[i]);
}
for(R int i=1;i<=mp[0];++i)
if(!vi[i])
if(dfs(i,i))++ans;
printf("%d",ans);
return 0;
}
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<queue>
#include<vector>
#define R register
using namespace std;
inline int read()
{
int f=1,x=0;char ch=getchar();
while(ch>'9'||ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch<='9'&&ch>='0'){x=(x<<3)+(x<<1)+(ch^48);ch=getchar();}
return f*x;
}
const int maxn=1000005;
struct node{
int v,nxt,da;
}e[2*maxn];int h[maxn],nu;
void add(int x,int y,int fl)
{
e[++nu].v=y;
e[nu].da=fl;
e[nu].nxt=h[x];
h[x]=nu;
}
int n,f[maxn],ans;
int dfs(int x,int xf)
{
int cnt=0;
for(int i=h[x];i;i=e[i].nxt)
{
int y=e[i].v,k=e[i].da;
if(y==xf)continue;
int nw=dfs(y,x);
//cout<<x<<" "<<y<<" "<<k<<endl;
if(k==1){cnt++;continue;}
if(!nw)continue;
if(k==3)ans++;
else cnt++;
}
ans+=cnt/2;
if(cnt%2==0)return 0;
return 1;
}
int main()
{
//freopen("data","r",stdin);
n=read();
int qj1=1,num1=0;
for(int x=2;x<=n;++x)
{
int y=read(),s=read(),t=read(),fl;
if(t==0)fl=2;
if(s==0&&t==1)num1++,fl=1;
if(s==1&&t==1)fl=3;
add(x,y,fl);
add(y,x,fl);
}
int nw=dfs(1,0);
ans+=nw;
printf("%d\n",ans);
}/*
g++ 1.cpp -o 1
./1 */

最新文章

  1. 新人入职100天,聊聊自己的经验&amp;教训
  2. WPF平台Grid控件性能比较
  3. (转)R空间数据处理与可视化
  4. ecshop 调用收货地址
  5. Android源码网站
  6. mapreduce实现全局排序
  7. 解决vsftpd 2.2.2读取目录列表失败的问题
  8. 路由器to路由器
  9. MTK如何烧录IMEI码(俗称串号)
  10. (python3爬虫实战-第一篇)利用requests+正则抓取猫眼电影热映口碑榜
  11. eclipse安装及配置pydev
  12. .net MVC4一个登陆界面加验证
  13. 类Shiro权限校验框架的设计和实现
  14. Selenium + Chrome headless 报ERROR:gpu_process_transport_factory.cc(1007)] Lost UI shared context 可忽略并配置不输出日志
  15. 从源码层面聊聊面试问烂了的 Spring AOP与SpringMVC
  16. day 55 linux 的常用命令
  17. 随笔教程:FastAdmin 如何打开新的标签页
  18. 老生常谈combobox和combotree模糊查询
  19. C++入门(2)
  20. MPTCP 理解

热门文章

  1. C#事件总线
  2. 适用于windows10 Linux子系统的安装管理配置 How To Management Windows Subsystem for Linux WSL
  3. [OS] 汇编语言
  4. CentOS8.2集成的megaraid_sas版本不支持IBM X3850 X5内置RAID卡。需要更新https://docs.broadcom.com/docs/MR_LINUX_DRIVER_7.15-07.715.02.00-1-PUL.tgz
  5. 【Git】git clone报错 git fatal: Unable to find remote helper for &#39;https&#39;
  6. Zabbix 监控过程详解
  7. cron 任务的典型格式是: 分钟(0-59) 小时(0-24) 日(1-31) 月(1-12) 星期(0-6) 要执行的命令
  8. docker部署harbor私有镜像库(3)
  9. 056.Python前端Django模型ORM多表基本操作
  10. JQuery Ajax 请求参数 List 集合处理