[***]HZOJ 哪一天她能重回我身边
%%%神仙题。
居然是图论,我还一直以为是二分图或者啥数据结构。
直接说正解了,将数看作节点,牌看做边,从牌的正面的数想反面连边权为1的边,反面向正面连边权为0的边(注意用到成对存储的技巧,之后会非常巧妙地用到),可以发现就是要求反转几条边可以使每个点的出读小于等于1。那么每个联通图只可能是树或基环树。可以先dfs判断求出每个联通图的点数np和边数ne,若ne/2(双向边)>np,那么这个联通图不合法直接输出-1 -1即可。
void dfs(int x,int fa)
{
vi[x]=;np++;
for(int i=f(x);i;i=n(i))
{
ne++;
if(v(i)!=fa)
if(!vi[v(i)])dfs(v(i),x);
}
}
bool pd()
{
for(int i=;i<=n*;i++)
if(!vi[i])
{
np=ne=,dfs(i,);
if(np<ne/)return ;
}
return ;
}
代码实现
接下来考虑他是树的情况:
对于确定的跟节点,翻转的边的个数就是将所有点指向父亲节点(可以动手画一下),可以用树形dp求得。但是要枚举根节点吗?其实可以用到二次扫描和换根法,设以x为根要反转的边数为f[x],那么其实f[son]可以用f[x]更新:如果x->son的边权为1,则f[son]=f[x]-1,否则f[son]=f[x]+1.这样我们就解决了树的情况。
int f[MAXN],st,en,ned;
void dfs1(int x,int fa)
{
v[x]=;f[x]=;
for(int i=f(x);i;i=n(i))
if(v(i)!=fa)
{
if(!v[v(i)])
{
dfs1(v(i),x);
f[x]+=f[v(i)]+w(i);
}
else st=u(i),en=v(i),ned=i;
}
}
int f2[MAXN];
vector<int> tem;
void dfs2(int x,int fa)
{
tem.push_back(f2[x]);
for(int i=f(x);i;i=n(i))
if(v(i)!=fa && i!=ned && i!=(ned^))
{
if(w(i))f2[v(i)]=f2[x]-;
else f2[v(i)]=f2[x]+;
dfs2(v(i),x);
}
}
代码实现
下面看基环树:
在dfs时找出环上的随机一条边记录,将它去掉按树处理,最后在考虑这条边的影响。那么边的成对储存就有用了,将边的编号%2就是它从u指向v的权值。
ned%=;
if(f2[st]+ned==f2[en]+(ned^))minn=;
else minn=;
ans+=min(f2[st]+ned,f2[en]+(ned^));
代码实现
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#define MAXN 200010
#define mod 998244353
#define LL long long
#define int LL
#define ma(x) memset(x,0,sizeof(x))
using namespace std;
struct edge
{
int u,v,w,nxt;
#define u(x) ed[x].u
#define v(x) ed[x].v
#define w(x) ed[x].w
#define n(x) ed[x].nxt
}ed[MAXN*];
int first[MAXN],num_e=;
#define f(x) first[x]
int T,n; int np,ne;
bool v[MAXN],vi[MAXN];
void dfs(int x,int fa)
{
vi[x]=;np++;
for(int i=f(x);i;i=n(i))
{
ne++;
if(v(i)!=fa)
if(!vi[v(i)])dfs(v(i),x);
}
}
bool pd()
{
for(int i=;i<=n*;i++)
if(!vi[i])
{
np=ne=,dfs(i,);
if(np<ne/)return ;
}
return ;
}
int f[MAXN],st,en,ned;
void dfs1(int x,int fa)
{
v[x]=;f[x]=;
for(int i=f(x);i;i=n(i))
if(v(i)!=fa)
{
if(!v[v(i)])
{
dfs1(v(i),x);
f[x]+=f[v(i)]+w(i);
}
else st=u(i),en=v(i),ned=i;
}
}
int f2[MAXN];
vector<int> tem;
void dfs2(int x,int fa)
{
// v[x]=1;
tem.push_back(f2[x]);
for(int i=f(x);i;i=n(i))
if(v(i)!=fa && i!=ned && i!=(ned^))
{
if(w(i))f2[v(i)]=f2[x]-;
else f2[v(i)]=f2[x]+;
// if(!v[v(i)])
dfs2(v(i),x);
}
}
inline void add(int u,int v,int w);
signed main()
{
// freopen("back5.in","r",stdin);
// freopen("1.out","w",stdout); cin>>T;
while(T--)
{
ma(f);ma(f2);ma(v);ma(vi);ma(first);num_e=;tem.clear();
scanf("%lld",&n);
int a,b;
for(int i=;i<=n;i++)
{
scanf("%lld%lld",&a,&b);
add(a,b,);add(b,a,);
}
if(pd()){puts("-1 -1");continue;}
int minn=,ans=,ans2=;
for(int i=;i<=n*;i++)
if(!v[i])
{
st=en=ned=-;tem.clear();minn=;
dfs1(i,);
f2[i]=f[i];
dfs2(i,);
if(st==-)
{
sort(tem.begin(),tem.end());
for(int j=;j<tem.size();j++)
if(tem[j]==tem[])minn++;
else break;
ans+=tem[];
}
else
{
ned%=;
if(f2[st]+ned==f2[en]+(ned^))minn=;
else minn=;
ans+=min(f2[st]+ned,f2[en]+(ned^));
}
ans2=(ans2*minn)%mod;
}
printf("%lld %lld\n",ans,ans2);
}
}
inline void add(int u,int v,int w)
{
++num_e;
u(num_e)=u;
v(num_e)=v;
w(num_e)=w;
n(num_e)=f(u);
f(u)=num_e;
}
完整代码
[***]HZOJ 哪一天她能重回我身边的更多相关文章
- Noip模拟77 2021.10.15
T1 最大或 $T1$因为没有开$1ll$右移给炸掉了,调了一年不知道为啥,最后实在不懂了 换成$pow$就过掉了,但是考场上这题耽误了太多时间,后面的题也就没办法好好打了.... 以后一定要注意右移 ...
- $dy$讲课总结
字符串: 1.广义后缀自动机(大小为\(m\))上跑一个长度为\(n\)的串,所有匹配位置及在\(parent\)树上其祖先的数量的和为\(min(n^2,m)\),单次最劣是\(O(m)\). 但是 ...
- 重回博客 谈一谈Node中的异步和单线程
重回博客,这个帐号之前注册后就只发了一篇博客.听朋友建议,决定一周两次更新. 第一篇谈论一下最近想的比较多的异步的问题. 传统多线程异步 传统的异步是多线程的,当要同时做两件事的时候,他们是执行在不同 ...
- Python之父重回决策层
在Guido van Rossum(吉多·范罗苏姆)卸任BDFL(“终身仁慈独裁者”)一职半年多之后,Python社区迎来了新的治理新方案:指导委员会模式,而经过投票Guido van Rossum也 ...
- Python之父重回决策层,社区未来如何发展?
春节假期结束了,大家陆续地重回到原来的生活轨道上.假期是一个很好的休息与调节的机会,同时,春节还有辞旧迎新的本意,它是新的轮回的开端. 在 Python 社区里,刚发生了一件大事,同样有开启新纪元的意 ...
- 《重回耶路撒冷——犹太人的三千年》(Return to Jerusalem)读后感
写在前面 书名:<重回耶路撒冷——犹太人的三千年>(Return to Jerusalem) 作者:张力升 来源:长清图书馆 阅读用时:其实年前拿到书,本来想寒假在家看的,但是在家一点儿都 ...
- Rabbitmq——实现消费端限流 --NACK重回队列
如果是高并发下,rabbitmq服务器上收到成千上万条消息,那么当打开消费端时,这些消息必定喷涌而来,导致消费端消费不过来甚至挂掉都有可能. 在非自动确认的模式下,可以采用限流模式,rabbitmq ...
- 两年,VMware又重回巅峰?
两年前,被公有云和容器打的焦头烂额的VMware一度被众多业界人士看衰,营收.股价双双下滑.然而,仅仅经过短短两年时间,VMware已经和AWS,IBM.微软.Rackspace等众多公有云厂商成为合 ...
- 纳德拉再造微软:市值如何重回第一阵营(思维确实变了,不再是以windows为中心,拥抱其它各种平台,敢在主战场之外找到适合自己的新战场)
有人说,现在的美国硅谷充满了“咖喱味”.也有人说,硅谷已经变成“印度谷”.原因就在于,以微软CEO萨提亚·纳德拉.谷歌CEO桑达尔·皮查伊为代表的印度人,近年以来掌控了全世界最令人望而生畏的科技巨头. ...
随机推荐
- 【solr】Solr5.5.4单机部署
Solr5.5.4单机部署 Solr5和Solr4有很大区别,最为明显的就是Solr5已经可以独立部署,从Solr5开始,Solr已经不再以war包形式部署,Solr已经成为了一个独立的java服务端 ...
- JSP内置对象解析
out对象:(PrintWriter类的实例) 用来向客户端输出信息,除了输出各种信息外还负责对缓冲区进行管理: 主要方法: print / println void 输出数据 newLine() v ...
- win10 下安装docker,创建镜像,push镜像到私有仓库,创建私有仓库,修改镜像仓库地址
通过连接下载window docker安装文件,https://download.docker.com/win/stable/Docker%20for%20Windows%20Installer.ex ...
- jS生成二叉树,二叉树的遍历,查找以及插入
js递归,二叉树的操作 //递归算法n次幂 function foo(n) { if (n == 1) { return 1; } else { return n * foo(n - 1); } } ...
- Javaweb项目中出现java.sql.SQLException: The server time zone value '�й���ʱ��' is unrecognized or represents more than one time zone.异常
javaweb项目中java.sql.SQLException: The server time zone value '�й���ʱ��' is unrecognized or represent ...
- python OneHot编码
- linux性能监视工具sar
sar是一个优秀的一般性能监视工具,它可以输出Linux所完成的几乎所有工作的数据.sar命令在sysetat rpm中提供.示例中使用sysstat版本5.0.5,这是稳定的最新版本之一.关于版本和 ...
- angular.module()创建、获取、注册angular中的模块
// 传递参数不止一个,代表新建模块;空数组代表该模块不依赖其他模块 var createModule = angular.module("myModule", []); // 只 ...
- HTML input type=file文件选择表单的汇总(二)
1. 原生file input大小.按钮文字等UI自定义 元素input的原生样式,不是太好看: 有一种方法是这样的:让file类型的元素透明度0,覆盖在我们好看的按钮上.然后我们去点击好看的按钮,实 ...
- go 文件操作 io
package main import ( "fmt" "os" ) func main() { //打开文件 //概念说明: file 的叫法 //1. fi ...