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 ...
随机推荐
- shell条件判断if中的-a到-z的意思
[ -a FILE ] 如果 FILE 存在则为真. [ -b FILE ] 如果 FILE 存在且是一个块特殊文件则为真. [ -c FILE ] 如果 FILE 存在且是一个字特殊文件则 ...
- Dynamics CRM日期字段查询使用时分秒的方法
本人微信公众号:微软动态CRM专家罗勇 ,回复293或者20190110可方便获取本文,同时可以在第一间得到我发布的最新博文信息,follow me!我的网站是 www.luoyong.me . 我们 ...
- 开源ERP-成功案例分析(3)
Odoo用户概要 关于Odoo全球的用户,我们来看一些数据: Odoo目前全球有300万使用者 Odoo系统上每天新创建的数据库超过1000个 Odoo和Word.Excel.PowerPoint一样 ...
- arcgis api 3.x for js 入门开发系列八聚合效果(附源码下载)
前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...
- android viewpage预加载和懒加载问题
1.本人理解懒加载和预加载问题某种情况下可以归结为一类问题,下面我就说一下我遇到的预加载问题和懒加载问题及解决的相应方法: - [1 ] 预加载问题 描述:我用到了三个fragment. ...
- c#二进制移位运算符 "<<"及">>","&","|","^"
移位运算符 & :按位与,其实与&&逻辑运算符有一致的地方: | :按位或,同样与||有类似的地方. ~:按位取反 ^:按位异或 <<:左移运算符 >> ...
- ansible学习基础知识和模块(一)
基础知识补充: 常用自动化运维工具 Ansible:使用python来开发的,无需设置Agentless(代理),一般管理几百台.与ssh的方式也不一样,ssh是基于c/s模式(客户端+服务器)来使用 ...
- 周末班:Python基础之网络编程
一.楔子 你现在已经学会了写python代码,假如你写了两个python文件a.py和b.py,分别去运行,你就会发现,这两个python的文件分别运行的很好.但是如果这两个程序之间想要传递一个数据, ...
- Windows 版 SourceTree 免登录跳过初始设置的方法
首先去官网下载最新的sourcetree安装包,点击打开下载地址. 下载完成后安装,等到他自启动开始提示你登录的时候,打开“我的电脑(此电脑)”,在最上边的输入栏输入%LocalAppData%\At ...
- 通过ip查询自己电脑的共享文件夹
查看电脑所有的共享文件或文件夹的三种方法如下: 方法一. 右键点击网上邻居,点击属性进入网上邻居属性页面. 选中本地连接,在窗口的左下方有详细信息,可以看到内网IP,记住IP地址. 直接在地址栏输入记 ...