codeforces 786E ALT
题目链接:CF786E
输出方案暗示网络流
我们考虑最朴素的建图
由源点\(s\)连向所有人,容量为1;树上所有的边视作节点连向\(t\),流量为1;人向其路径上所有的树边连边,流量为\(inf\),跑最小割即可
然而我们发现这样的话网络图中的边的数据规模达到了\(O(n^2)\),肯定炸掉
于是考虑优化建图
我们将一条路径拆成\(log\)段,用\((i,j)\)表示由节点\(i\)跳到其\(2^j\)层父亲
注意到\((i,j)\)包含着\((i,j-1),(i+2^{j-1},j-1)\),因此我们考虑也将其连上容量为\(inf\)的边(类似于标记下放?不熟悉的可以做SCOI2016萌萌哒,一个区间上的问题)
原来的图中将树边连向\(t\)也就变成了将边\((i,0)\)连向\(t\)(此时\(t>1\))
那么新图的点数和边数的规模均维持在\(O(nlogn)\)可以维护
然而毒瘤题还要输出方案
我们考虑从源点\(dfs\),如果当前找到的一条边有流量说明还未割开
如果代表人的点被割开说明要标记这个人;如果某条原来与\(t\)相连的树边未被割开说明要标记这一条树边
预处理时存下相对应的编号即可
#include<iostream>
#include<string.h>
#include<string>
#include<stdio.h>
#include<algorithm>
#include<math.h>
#include<vector>
#include<queue>
#include<map>
#include<set>
using namespace std;
#define lowbit(x) (x)&(-x)
#define rep(i,a,b) for (int i=a;i<=b;i++)
#define per(i,a,b) for (int i=a;i>=b;i--)
#define maxd 1000000007
typedef long long ll;
const int N=100000;
const double pi=acos(-1.0);
struct treenode{
int to,nxt,id;
}tree[40040];
int all1=0,head1[40040];
struct flownode{
int to,nxt,flow;
}sq[10004000];
int all=1,head[501000],cur[500500],dept[500500];
bool vis[500500];
queue<int> q;
int n,m,st[20020][20],fa[20020][20],tot=0,dep[20020],s,t,
a[500500],b[500500];
int read()
{
int x=0,f=1;char ch=getchar();
while ((ch<'0') || (ch>'9')) {if (ch=='-') f=-1;ch=getchar();}
while ((ch>='0') && (ch<='9')) {x=x*10+(ch-'0');ch=getchar();}
return x*f;
}
void addedge(int u,int v,int id)
{
all1++;tree[all1].nxt=head1[u];tree[all1].to=v;tree[all1].id=id;head1[u]=all1;
}
void add(int u,int v,int f)
{
all++;sq[all].nxt=head[u];sq[all].to=v;sq[all].flow=f;head[u]=all;
all++;sq[all].nxt=head[v];sq[all].to=u;sq[all].flow=0;head[v]=all;
}
void dfs(int u,int fu)
{
dep[u]=dep[fu]+1;fa[u][0]=fu;
rep(i,1,15) st[u][i]=(++tot);
rep(i,1,15)
{
if (fa[u][i-1])
{
fa[u][i]=fa[fa[u][i-1]][i-1];
add(st[u][i],st[u][i-1],maxd);
add(st[u][i],st[fa[u][i-1]][i-1],maxd);
}
}
int i;
for (i=head1[u];i;i=tree[i].nxt)
{
int v=tree[i].to;
if (v==fu) continue;
st[v][0]=(++tot);b[tree[i].id]=tot;
dfs(v,u);
}
}
void query_lca(int u,int v,int now)
{
if (dep[u]<dep[v]) swap(u,v);
int tmp=dep[u]-dep[v];
per(i,15,0)
{
if ((tmp>>i)&1)
{
add(now,st[u][i],maxd);
u=fa[u][i];
}
}
if (u==v) return;
per(i,15,0)
{
if (fa[u][i]!=fa[v][i])
{
add(now,st[u][i],maxd);add(now,st[v][i],maxd);
u=fa[u][i];v=fa[v][i];
}
}
add(now,st[u][0],maxd);add(now,st[v][0],maxd);
}
void init()
{
n=read();m=read();
rep(i,1,n-1)
{
int u=read(),v=read();
addedge(u,v,i);addedge(v,u,i);
}
rep(i,0,15) st[0][i]=(++tot);st[1][0]=(++tot);
dfs(1,0);
rep(i,1,m)
{
a[i]=(++tot);add(s,tot,1);
int u=read(),v=read();
query_lca(u,v,tot);
}
t=(++tot);
rep(i,2,n) add(st[i][0],t,1);
}
bool bfs()
{
memset(vis,0,sizeof(vis));
memset(dept,0,sizeof(dept));
q.push(s);vis[s]=1;
while (!q.empty())
{
int u=q.front(),i;q.pop();
for (i=head[u];i;i=sq[i].nxt)
{
int v=sq[i].to;
if ((sq[i].flow) && (!vis[v]))
{
vis[v]=1;q.push(v);
dept[v]=dept[u]+1;
}
}
}
if (!vis[t]) return 0;
rep(i,0,t) cur[i]=head[i];
return 1;
}
int dfs(int now,int t,int lim)
{
if ((!lim) || (now==t)) return lim;
int i,sum=0;
for (i=cur[now];i;i=sq[i].nxt)
{
int v=sq[i].to;cur[now]=i;
if (dept[v]==dept[now]+1)
{
int f=dfs(v,t,min(sq[i].flow,lim));
if (f)
{
sq[i].flow-=f;
sq[i^1].flow+=f;
sum+=f;lim-=f;
if (!lim) break;
}
}
}
return sum;
}
void dfsans(int u)
{
vis[u]=1;
int i;
for (i=head[u];i;i=sq[i].nxt)
{
int v=sq[i].to;
if ((!vis[v]) && (sq[i].flow)) dfsans(v);
}
}
void work()
{
int ans=0;
while (bfs()) ans+=dfs(s,t,maxd);
memset(vis,0,sizeof(vis));
dfsans(0);
printf("%d\n",ans);
int cnt=0;
rep(i,1,m) if (!vis[a[i]]) cnt++;
printf("%d ",cnt);
rep(i,1,m) if (!vis[a[i]]) printf("%d ",i);printf("\n");
cnt=0;
rep(i,1,n-1) if (vis[b[i]]) cnt++;
printf("%d ",cnt);
rep(i,1,n-1) if (vis[b[i]]) printf("%d ",i);
}
int main()
{
init();
work();
return 0;
}
codeforces 786E ALT的更多相关文章
- Codeforces 786E. ALT 最小割+倍增
E. ALT http://codeforces.com/problemset/problem/786/E 题意: 给出一棵 n 个节点的树与 m 个工人.每个工人有一条上下班路线(简单路径),一个工 ...
- 【Codeforces】【网络流】【树链剖分】【线段树】ALT (CodeForces - 786E)
题意 现在有m个人,每一个人都特别喜欢狗.另外还有一棵n个节点的树. 现在每个人都想要从树上的某个节点走到另外一个节点,且满足要么这个人自带一条狗m,要么他经过的所有边h上都有一条狗. 2<=n ...
- 【Codeforces】【#295】【Div.1】
嘛,一直以来蒟蒻都没怎么打过CF……现在还是蓝名狗……今天跟着zyf打了一场virtual,果断一题滚粗
- CodeForces - 344A Magnets (模拟题)
CodeForces - 344A id=46664" style="color:blue; text-decoration:none">Magnets Time ...
- python爬虫学习(5) —— 扒一下codeforces题面
上一次我们拿学校的URP做了个小小的demo.... 其实我们还可以把每个学生的证件照爬下来做成一个证件照校花校草评比 另外也可以写一个物理实验自动选课... 但是出于多种原因,,还是绕开这些敏感话题 ...
- [No000093]按住Alt 再按数字键敲出任意汉字和字符!
1.在notepad里,(中文系统下) 按住Alt 然后按52946最后放开Alt 按住Alt 然后按45230最后放开Alt 按住Alt 然后按50403最后放开Alt 你会看到"我爱你& ...
- [No00008B]远程桌面发送“Ctrl+Alt+Delete”组合键调用任务管理器
向远程桌面发送"Ctrl+Alt+Delete"组合键的两种方法 1.在本地按下Ctrl+Alt+End,可以成功发送"Ctrl+Alt+Delete"组合键! ...
- 平常看到的Alt+xx 快捷键用法
1. 先按Alt, 哪一个菜单对应的字符是有划线的. 2. 输入对应的字符打开相应的菜单, 3 再输入相应的字符打开子菜单
- 【Codeforces 738D】Sea Battle(贪心)
http://codeforces.com/contest/738/problem/D Galya is playing one-dimensional Sea Battle on a 1 × n g ...
随机推荐
- Thrift 入门教程
1. 概述 thrift是一个软件框架,用来进行可扩展且跨语言的服务的开发.它结合了功能强大的软件堆栈和代码生成引擎,以构建在 C++, Java, Go,Python, PHP, Ruby, Erl ...
- 广州.NET微软技术俱乐部 微信群有用信息集锦
考虑到广州.NET微软技术俱乐部 微信群 十分活跃. 有用信息很有可能被淹没. 所以建立此贴. 首先群的活跃是十分重要的. 所以我是不可能把群搞得像技术论坛和github一样, 因为微信群的定位我在& ...
- android 记一次富文本加载之路
文章链接:https://mp.weixin.qq.com/s/69TRkmFL1aNuSqfw4ULMJw 项目中经常涉及到富文本的加载,后台管理端编辑器生成的一段html 代码要渲染到移动端上面, ...
- myapp——自动生成小学四则运算题目的命令行程序(侯国鑫 谢嘉帆)
1.Github项目地址 https://github.com/baiyexing/myapp.git 2.功能要求 题目:实现一个自动生成小学四则运算题目的命令行程序 功能(已全部实现) 使用 -n ...
- SQL 创建分区表
(以项目中实际使用的GNSS库为例) 背景:数据量巨大,定时创建月表存放数据,月表中数据存放在不同的文件组中来提高查询效率 一.创建数据库,添加文件组 除了逻辑文件和物理文件的分离之外,SQL S ...
- MySQL常用数值函数
数值函数: 用来处理很多数值方面的运算,使用数值函数,可以免去很多繁杂的判断求值的过程,能够大大提高用户的工作效率. 1.ABS(x):返回 x 的绝对值 mysql> select abs(- ...
- 苹果ios系统无法通过RD Client连接win10服务器远程错误0x00001307
问题描述: 1.RD Client无法远程Windows 10桌面,提示“错误 用户名或密码错误” 之前连接是没有问题的,但是更新了win10系统以后就出现问题了 [解决方法]: 最后找到了原因是因为 ...
- Unix、Windows、Mac OS、Linux系统故事
我们熟知的操作系统大概都是windows系列,近年来Apple的成功,让MacOS也逐渐走进普通用户.在服务器领域,恐怕Linux是无人不知无人不晓.他们都是操作系统,也在自己的领域里独领风骚.这都还 ...
- gitlab-server环境搭建
1.安装GitLab的需求 操作系统 受支持的Unix衍生版 Ubuntu Debian CentOS Red Hat Enterprise Linux (使用CentOS的包和命令) Scienti ...
- yum源 Python3 Django mysql安装
yum 源安装 yum源位置: yum源仓库的地址 在/etc/yum.repos.d/,并且只能读出第一层的repo文件 yum仓库的文件都是以.repo结尾的 linux软件包管理 yum工具如同 ...