Codeforces 786E. ALT 最小割+倍增
E. ALT
http://codeforces.com/problemset/problem/786/E
题意:
给出一棵 n 个节点的树与 m 个工人。
每个工人有一条上下班路线(简单路径),一个工人会得到满足只要下面一项满足:
1、他得到一只puppy
2、他的上下班路径上每条边都有一只doge
求使所有工人满足的最小dog数并输出方案。n≤20000,m≤10000
想法:暴力建图,源点连向工人Xi,边Yi连向汇点,容量为1。然后工人向其路径上的边连容量为1的边。O(nm)
优化建图:路径为树上连续路径,那么可以套上树链剖分变成连续区间,再用线段树优化连边....O(mlog^2n)。
反正不带修改,那么求树上路径问题还可以用点分治和倍增。O(mlogn)
点分治:对于同一个重心,维护一条轨道,通过轨道可以到达这个点到重心所有点。
具体:add(D[i],Y[i]),add(D[i],D[i-1]);
倍增:可以形象成树上一条链被拆分成若干个区间,步长为2^j,大区间向其包含的小区间连边,这个类似线段树优化建边。具体:add(G[j][x],G[j-1][x]),add(G[j][x],G[j-1][ F[j-1][x] ]);
最小割方案的输出:对于Xi如果划分到{T}集合,那么他与源点的边就被割了,他得到了一只puppy。如果Yi被划分到{S},那么它与汇点的边被割了,一只doge放在这条边上。
附上最小割+倍增的代码(点分治好麻烦....懒癌晚期患者表示不想写)
#include<cstdio>
#include<cmath>
#include<vector>
const int len(),N(),INF(0x7fffffff);
struct Node{int nd,nx,pos;}bot[len*+];int tot,first[len+],v,u;
int f[][len+],g[][len+],logg,depth[len+],pos[len+];
struct Data{int nd,fl,nx;};
std::vector<Data>Edge[N+];int S,T;
int n,m,ans,now,last,st[len+],top,flag[N+];;
int min(int a,int b){return a>b?b:a;}
void swap(int &a,int &b){if(a==b)return;a^=b;b^=a;a^=b;}
void add(int a,int b,int p){bot[++tot]=(Node){b,first[a],p};first[a]=tot;}
void addedge(int a,int b,int f)
{
Edge[a].push_back((Data){b,f,(int)Edge[b].size()});
Edge[b].push_back((Data){a,,(int)Edge[a].size()-});
}
template <class T>void read(T &x)
{
x=;char ch=getchar();
while(ch<''||ch>'')ch=getchar();
while(ch>=''&&ch<=''){x=x*+ch-'';ch=getchar();}
}
void update(int x)
{
for(int j=;j<=logg;j++)
{
f[j][x]=f[j-][ f[j-][x] ];
g[j][x]=++now;
addedge(g[j][x],g[j-][x],INF);
addedge(g[j][x],g[j-][ f[j-][x] ],INF);
}
}
void Dfs(int x,int fa)
{
f[][x]=fa; g[][x]=x;
update(x); depth[x]=depth[fa]+;
for(int v=first[x];v;v=bot[v].nx)
if(bot[v].nd!=fa) pos[bot[v].nd]=bot[v].pos,Dfs(bot[v].nd,x);
}
int lca(int u,int v)
{
if(depth[u]<depth[v])swap(u,v);
for(int k=depth[u]-depth[v],j=;k;k>>=,j++) if(k&)u=f[j][u];
if(u==v)return u;
for(int j=logg;j>=&&f[][v]!=f[][u];j--)
if(f[j][u]!=f[j][v])u=f[j][u],v=f[j][v];
return f[][v];
}
void link(int x,int y,int t)
{
for(int k=depth[x]-depth[t],j=;k;k>>=,j++)//LCA不选
if(k&)addedge(now,g[j][x],INF),x=f[j][x];
for(int k=depth[y]-depth[t],j=;k;k>>=,j++)//LCA不选
if(k&)addedge(now,g[j][y],INF),y=f[j][y];
}
void DFS_Put(int x)
{
flag[x]=;
for(int v=,sz=Edge[x].size();v<sz;v++)
{
Data y=Edge[x][v];
if(y.fl&&!flag[y.nd])DFS_Put(y.nd);
}
}
int q[N+],l,h,dis[N+];
bool bfs(int s,int t)
{
for(int i=;i<=T;i++)dis[i]=INF;
q[l=]=s; h=; dis[s]=;
while(h<l)
{
int x=q[++h];
for(int v=,sz=Edge[x].size();v<sz;v++)
{
Data y=Edge[x][v];
if(y.fl&&dis[y.nd]==INF)
dis[y.nd]=dis[x]+,q[++l]=y.nd;
}
}
return dis[t]!=INF;
}
int dfs(int x,int t,int flow)
{
if(x==t)return flow;
int sum=,tmp;
for(int v=,sz=Edge[x].size();v<sz;v++)
{
Data y=Edge[x][v];
if(y.fl&&dis[y.nd]==dis[x]+)
{
tmp=dfs(y.nd,t,min(y.fl,flow));
flow-=tmp; sum+=tmp;
Edge[x][v].fl-=tmp;
Edge[y.nd][y.nx].fl+=tmp;
if(!flow)break;
}
}
if(!sum)dis[x]=-;
return sum;
} int main()
{
read(n),read(m);logg=log2(n);
for(int i=;i<n;i++)
{
read(u),read(v);
add(u,v,i),add(v,u,i);
}
now=n;
Dfs(,);
S=now+m+; T=S+; last=now;
for(int i=;i<=n;i++)addedge(i,T,);
for(int i=,Lt;i<=m;i++)
{
read(v),read(u);
now++; addedge(S,now,);
Lt=lca(v,u);
link(v,u,Lt);
}
while(bfs(S,T))ans+=dfs(S,T,INF);
printf("%d\n",ans);
DFS_Put(S);
for(int i=;i<=m;i++) if(!flag[i+last])st[++top]=i;
printf("%d ",top);
while(top)printf("%d ",st[top--]);
for(int i=;i<=n;i++) if(flag[i])st[++top]=pos[i];
printf("\n");
printf("%d ",top);
while(top)printf("%d ",st[top--]);
return ;
}
Codeforces 786E. ALT 最小割+倍增的更多相关文章
- cf786E ALT (最小割+倍增优化建图)
如果把“我全都要”看作是我全不要的话,就可以用最小割解决啦 源点S,汇点T 我们试图让每个市民作为一个等待被割断的路径 把狗狗给市民:建边(S,i,1),其中i是市民 把狗狗给守卫:建边(j,T,1) ...
- codeforces 786E ALT
题目链接:CF786E 输出方案暗示网络流 我们考虑最朴素的建图 由源点\(s\)连向所有人,容量为1:树上所有的边视作节点连向\(t\),流量为1:人向其路径上所有的树边连边,流量为\(inf\), ...
- codeforces786E ALT【倍增+最小割】
方案二选一,显然是最小割,朴素的想法就是一排人点一排边点,分别向st连流量1的边,然后人点向路径上的边点连流量inf的边跑最大流 但是路径可能很长,这样边数就爆了,所以考虑倍增,然后倍增后大区间向小区 ...
- 【Codeforces】【网络流】【树链剖分】【线段树】ALT (CodeForces - 786E)
题意 现在有m个人,每一个人都特别喜欢狗.另外还有一棵n个节点的树. 现在每个人都想要从树上的某个节点走到另外一个节点,且满足要么这个人自带一条狗m,要么他经过的所有边h上都有一条狗. 2<=n ...
- Codeforces 724E Goods transportation(最小割转DP)
[题目链接] http://codeforces.com/problemset/problem/724/E [题目大意] 每个城市有pi的物品可以运出去卖,si个物品可以买, 编号小的城市可以往编号大 ...
- (2016北京集训十三)【xsy1532】网络战争 - 最小割树+树上倍增+KD树
题解: 好题!! 这题似乎能上我代码长度记录的前五? 调试时间长度应该也能上前五QAQ 首先题目要求的明显就是最小割,当然在整个森林上求Q次最小割肯定是会GG的,所以我们需要一个能快速求最小割的算法— ...
- Codeforces 1368H - Breadboard Capacity(最小割+线段树维护矩阵乘法)
Easy version:Codeforces 题面传送门 & 洛谷题面传送门 Hard version:Codeforces 题面传送门 & 洛谷题面传送门 首先看到这种从某一种颜色 ...
- Codeforces 628F 最大流转最小割
感觉和昨天写了的题一模一样... 这种题也能用hall定理取check, 感觉更最小割差不多. #include<bits/stdc++.h> #define LL long long # ...
- Codeforces 1009G Allowed Letters 最大流转最小割 sosdp
Allowed Letters 最直观的想法是贪心取, 然后网络流取check可不可行, 然后T了. 想到最大流可以等于最小割, 那么我们状压枚举字符代表的6个点连向汇点是否断掉, 然后再枚举64个本 ...
随机推荐
- tcp_fast_open的概念 作用以及实现(转)
引言 三次握手的过程中,当用户首次访问server时,发送syn包,server根据用户IP生成cookie,并与syn+ack一同发回client:client再次访问server时,在syn包携带 ...
- [WebMethod]的使用,ajax调用[WebMethod]的使用,webservice(web服务) asmx的使用,ajax调用[WebMethod]进行json传输
首先,要分为.net 2.0和.net 3.5这两种情况来考虑 一:.net 2.0情况下 ajax可以调用 aspx.cs 里面加了 [webmethod]的静态方法,而不能调用 asmx 里面加了 ...
- 异步和多线程,委托异步调用,Thread,ThreadPool,Task,Parallel,CancellationTokenSource
1 进程-线程-多线程,同步和异步2 异步使用和回调3 异步参数4 异步等待5 异步返回值 5 多线程的特点:不卡主线程.速度快.无序性7 thread:线程等待,回调,前台线程/后台线程, 8 th ...
- debian 7上源码编译MongoDB 3.4版本
此文已由作者温正湖授权网易云社区发布. 欢迎访问网易云社区,了解更多网易技术产品运营经验. 要想精通一个数据库,除了知道该数据库的功能特性.使用方法等,还需要能够看懂数据库源码,能够使用gdb工具对其 ...
- JavaScript巩固篇(一)——数据类型与全局变量、局部变量、垃圾回收机制、存储方式、生命周期
知识要点 数据类型 存储方式 全局变量与局部变量 变量的生命周期 垃圾回收机制 知识概览 数据类型 JavaScript的数据类型分为:基本类型.引用类型 本质区别: 基本数据类型的变量实际值存储在栈 ...
- Mac下安装rJava,xlsx,ReporteRs包
xlsx包可以用来读取excel数据,ReporteRs包可以用来直接输出word报告,这两个包都对rJava包有依赖,所以必须先安装rJava. (1)查看mac的java信息 java版本: &g ...
- atcode062D(预处理&优先队列)
题目链接:http://abc062.contest.atcoder.jp/tasks/arc074_b 题意:从3*n个元素中删除n个元素,使得剩余元素中前n个元素的和减后n个元素的和最大: 思路: ...
- Google Analytics & Webtrend 使用笔记
GA和webtrend中的参数,每每遇到了都记不住.遇到一点记一点好了... Page Views(PV): 浏览次数.用户每打开一个页面,记录为1个PV:用户多次打开同一个页面,PV累计多次. Da ...
- Java基础--常用API--字符串相关API
一.java.lang.String 1.string对象不可变,被final修饰,不能被继承. 2.赋值方式: (1)直接赋值.比如: String name = "rick"; ...
- 脑图和MarkDown
使用脑图整理前端体系 根据以下网址整理 http://web.jobbole.com/84062/ http://naotu.baidu.com/ 学习MarkDown语法格式 (一) 标题 在首行插 ...