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 ...
随机推荐
- arcgis api 3.x for js 入门开发系列七图层控制(附源码下载)
前言 关于本篇功能实现用到的 api 涉及类看不懂的,请参照 esri 官网的 arcgis api 3.x for js:esri 官网 api,里面详细的介绍 arcgis api 3.x 各个类 ...
- Android Studio撤销与SVN的关联
为何会记录这一个问题,主要是在做项目的过程中出现了一个奇怪的现象,就是直接在文件目录下使用svn上传文件的话,可以看到该目录是与SVN相关联的,可是到了用Android Studio上传代码的时候却发 ...
- json-gson:.isJsonNull()问题-堆栈溢出
不用管我下面的第一个答案.我读得太快了. 看起来这是一个简单的例子,文件撒谎-或者至少是被误解了.幸运的是,代码并不是那么简单,而且gson是一个开源项目. 这是 JsonObject.get(Str ...
- MySQL 处理海量数据时的一些优化查询速度方法
查询速度慢的原因 1.没有索引或者没有用到索引(这是查询慢最常见的问题,是程序设计的缺陷) 2.I/O 吞吐量小,形成了瓶颈效应. 3.没有创建计算列导致查询不优化. 4.内存不足 5.网络速度慢 6 ...
- macos 常用快捷键及操作
通用: 拷贝相当于window下的复制非苹果键盘(command == win option == alt control == ctrl)Command + C 拷贝(Copy)Command + ...
- c/c++ 继承与多态 容器与继承1
问题:类B公有继承类A,类A有虚函数fun,类B覆盖了虚函数fun,有一个std::vector<A>,添加A的对象a,和B的对象b,到这个容器里,然后从vector里取出来,使用对象a. ...
- C++Primer第五版学习笔记
<C++ Primer>Learning Note 程序实例下载地址:http://www.informit.com/title/0321714113 第一章 开始 ...
- Windows 下端口被占用
0. 参考 参考链接: Windows下如何查看某个端口被谁占用 1. 遇到的问题 在 Windows 下的 IDEA 中启动 Web 服务显示 8080 端口被占用,程序无法正确启动. 2. 解决 ...
- 周一01.4安装PyCharm步骤
安装集成开发工具 步骤一 步骤二 步骤三 步骤四
- 批处理基础知识-IF
本文主要介绍批处理IF命令的使用. IF命令格式: if /i string=string command 释义:判断2个字符串是否相等,但不区分大小写. 例: 代码: @echo off if /i ...