并不对劲的bzoj3832: [Poi2014]Rally
传送门->
这题的原理看上去很神奇。
称拓扑图中入度为0的点为“起点”,出度为0的点为“终点”。
因为“起点”和“终点”可能有很多个,算起来会很麻烦,所以新建“超级起点”S,向所有点连边,“超级终点”T,所有点向它连边。这样原图中的最长路就是新图中的最长路-2。
dis[a->b]表示a到b的距离。
对于一个拓扑图而言,它的一个割集中肯定有一条边在最长路上。对于每条边,可以将dis[S->该边起点]和dis[该边终点->T]算出,那么该边所在路径中的最长的一个就是dis[S->该边起点]+dis[该边终点->T]+1。将该边边权设为它。这样一来,最长路就是该图随便一个割集的边权最大值。
删掉一个点,就可以看成删掉这个点的所有出边。但是这样就有些问题了:所有能走到这条边的边和这条边能走到的所有边都会因为这条边删掉而受影响,要是把所有的影响都算出来,想必是不行的。这时就有一个看似可行的方法了:在删掉这个点的所有出边的图中求一个只包含与这些边不互达的边的割集,取这个割集中的边权最大值。会发现那个割集就是原图中由这个点的所有出边和一些与它不互达的边组成的一个割集。
会不会出现不互达的边不够用的情况?先把拓扑图按最长路分好层(浅蓝色的线)。

这样的话,就不会存在右->左的边。
也就是说,图中所有红边和所有蓝边都是不互达的。而删掉所有红边和所有蓝边后,就不能从左边走到右边了。这样就形成了一个割集。答案就是所有蓝边的边权最大值。
如果这个删掉的点后图变成两部分怎么办?想必是不可能的,因为对于每一个点,都有 S->该点 和 该点->T 的边,所以只要不删S、T就不会将图分成几部分。肯定会有上图中蓝边那样的边存在的。
那么问题就变成了对于每个点,求出所有与它不互达的边权的最大值,再对于所有点取最小值就行了!
好吧,这并没有把问题简化多少,至少变得相对可做了。
那么可以考虑递推。按照拓扑序枚举要删掉的点,每次将当前点变成下一个时,新的那个点的所有入边要删去,上一个点的所有出边要加入。
这是为什么呢?因为上一个状态是删掉上一个点的图,计入答案的是割集中不包括与上一个点可达的边的边权。加入上一个点的所有出边后,就刚好凑成了一个割集。此时计入答案的是原图的一个割集。但是我们要求的是删除新的点的割集,所以就要删除所有连向新的点的边。这时不会有其它与能走到该点的边。这是因为能走到该点的边的起点、终点的拓扑序都小于该点(终点是该点的边刚刚已经被删去了,不考虑)。也就是说,所有这些边的终点之前已经被考虑过了,它们的入边已经全部被删除了。而该点能到达的边的起点的拓扑序在该点之后,还没有被加入,所有不用考虑。
每次删除新的点的所有出边,会多删除吗?想必是不会的。新的点的所有入边的起点在拓扑序中都比该点靠前,所以所有入边之前都被加入了。
用什么数据结构维护呢?看上去需要支持取最大值、插入、删除,堆似乎不错。
刚刚证明了这种方法是可行的,但至于具体是怎么想出来的,我能说是去看某个大佬的博客吗?
#include<algorithm>
#include<cassert>
#include<cmath>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<iomanip>
#include<iostream>
#include<map>
#include<queue>
#include<stack>
#include<vector>
#define rep(i,x,y) for(register int i=(x);i<=(y);++i)
#define dwn(i,x,y) for(register int i=(x);i>=(y);--i)
#define re register
#define maxn 500010
#define maxm 2000010
using namespace std;
inline int read()
{
int x=0,f=1;
char ch=getchar();
while(isdigit(ch)==0 && ch!='-')ch=getchar();
if(ch=='-')f=-1,ch=getchar();
while(isdigit(ch))x=(x<<3)+(x<<1)+ch-'0',ch=getchar();
return x*f;
}
inline void write(int x)
{
int f=0;char ch[20];
if(!x){putchar('0'),putchar(' ');return;}
if(x<0){putchar('-');x=-x;}
while(x)ch[++f]=x%10+'0',x/=10;
while(f)putchar(ch[f--]);
putchar(' ');
}
int fir[2][maxn],nxt[2][maxm],v[2][maxm],id[2][maxm],cnt[2];//0:roads; 1:back roads;
int S,T,n,m,mx,mxnd;
int q[maxn],hd,tl,dis[2][maxn],in[maxn];
void ade(int u1,int v1,int id1,int f){v[f][cnt[f]]=v1,id[f][cnt[f]]=id1,nxt[f][cnt[f]]=fir[f][u1],fir[f][u1]=cnt[f]++;}
priority_queue<int>yes,no;
void inq(int x){yes.push(x);while(!no.empty()&&yes.top()==no.top())yes.pop(),no.pop();}
void deq(int x){no.push(x);while(!no.empty()&&yes.top()==no.top())yes.pop(),no.pop();}
int top(){while(!no.empty()&&yes.top()==no.top())yes.pop(),no.pop();return yes.top();}
int tmp[maxn],cntt;/*
void print()
{
cout<<"heap:"<<endl;
while(!no.empty()&&yes.top()==no.top())yes.pop(),no.pop();
while(!yes.empty())cout<<yes.top()<<" ",tmp[++cntt]=yes.top(),yes.pop();
while(cntt)yes.push(tmp[cntt--]);cout<<endl;
}*/
int main()
{
memset(fir,-1,sizeof(fir));
n=read(),m=read();
rep(i,1,m){int x=read(),y=read();ade(x,y,i,0),ade(y,x,i,1);in[y]++;}S=0,T=n+1;
rep(i,1,n)ade(S,i,i+m,0),ade(i,S,i+m,1),ade(i,T,i+m,0),ade(T,i,i+m,1),in[i]++,in[T]++;
q[++tl]=S;
while(hd<tl)
{
int u=q[++hd];
for(int k=fir[0][u];k!=-1;k=nxt[0][k])
{
int vv=v[0][k];in[vv]--;
if(in[vv]==0){q[++tl]=vv;}
}
}
rep(i,1,tl)
{
int u=q[i];
for(int k=fir[0][u];k!=-1;k=nxt[0][k])
{
int vv=v[0][k];
dis[0][vv]=max(dis[0][u]+1,dis[0][vv]);
}
}
dwn(i,tl,1)
{
int u=q[i];
for(int k=fir[0][u];k!=-1;k=nxt[0][k])
{
int vv=v[0][k];
dis[1][u]=max(dis[1][vv]+1,dis[1][u]);
}
}
mx=2147483647;
rep(i,2,tl-1)
{
int u=q[i],pu=q[i-1];
for(int k=fir[0][pu];k!=-1;k=nxt[0][k])
{
int vv=v[0][k];
inq(dis[0][pu]+dis[1][vv]+1);
}
for(int k=fir[1][u];k!=-1;k=nxt[1][k])
{
int vv=v[1][k];
deq(dis[0][vv]+dis[1][u]+1);
}
if(mx>top())mx=top(),mxnd=u;
}
write(mxnd),write(mx-2);
return 0;
}
/*
6 5
1 3
1 4
3 6
3 4
4 5
*/
并不对劲的bzoj3832: [Poi2014]Rally的更多相关文章
- BZOJ3832[Poi2014]Rally——权值线段树+拓扑排序
题目描述 An annual bicycle rally will soon begin in Byteburg. The bikers of Byteburg are natural long di ...
- BZOJ3832 [Poi2014]Rally 【拓扑序 + 堆】
题目链接 BZOJ3832 题解 神思路orz,根本不会做 设\(f[i]\)为到\(i\)的最长路,\(g[i]\)为\(i\)出发的最长路,二者可以拓扑序后\(dp\)求得 那么一条边\((u,v ...
- BZOJ3832 : [Poi2014]Rally
f[0][i]为i出发的最长路,f[1][i]为到i的最长路 新建源汇S,T,S向每个点连边,每个点向T连边 将所有点划分为两个集合S与T,一开始S中只有S,其它点都在T中 用一棵线段树维护所有连接属 ...
- BZOJ3832: [Poi2014]Rally(拓扑排序 堆)
题意 题目链接 Sol 最直观的思路是求出删除每个点后的最长路,我们考虑这玩意儿怎么求 设\(f[i]\)表示以\(i\)结尾的最长路长度,\(g[i]\)表示以\(i\)开始的最长路长度 根据DAG ...
- 【BZOJ3832】[POI2014]Rally(拓扑排序,动态规划)
[BZOJ3832][POI2014]Rally(拓扑排序,动态规划) 题面 BZOJ,权限题 洛谷 题解 这题好强啊,感觉学了好多东西似的. 首先发现了一个图画的很好的博客,戳这里 然后我来补充一下 ...
- 【BZOJ-3832】Rally 拓扑序 + 线段树 (神思路题!)
3832: [Poi2014]Rally Time Limit: 20 Sec Memory Limit: 128 MBSec Special JudgeSubmit: 168 Solved: ...
- 3832: [Poi2014]Rally
3832: [Poi2014]Rally 链接 分析: 首先可以考虑删除掉一个点后,计算最长路. 设$f[i]$表示从起点到i的最长路,$g[i]$表示从i出发到终点的最长路.那么经过一条边的最长路就 ...
- [POI2014]Rally
OJ题号:BZOJ3832.洛谷3573 思路: 建立超级源汇$S$和$T$,DP求出分别以$S$和$T$为源点的最长路$diss$和$dist$. 对于每条边$i$,设定一个权值$w_i=diss_ ...
- 【bzoj3832】Rally
Portal -->bzoj3832 Description 给你一个DAG,每条边长度都是\(1\),请找一个点满足删掉这个点之后剩余图中的最长路最短 Solution 这题的话感觉 ...
随机推荐
- datatable生成easyui的json格式汇总( 转)
转自 http://www.cnblogs.com/WikStone/archive/2012/07/02/2573137.html 目前项目没有使用第三方的json转换库,都是根据json格式进行字 ...
- POJ1780 Code
KEY公司开发出一种新的保险箱.要打开保险箱,不需要钥匙,但需要输入一个正确的.由n位数字组成的编码.这种保险箱有几种类型,从给小孩子玩的玩具(2位数字编码)到军用型的保险箱(6位数字编码).当正确地 ...
- [POJ3041] Asteroids(最小点覆盖-匈牙利算法)
传送门 题意: 给一个N*N的矩阵,有些格子有障碍,要求我们消除这些障碍,问每次消除一行或一列的障碍,最少要几次. 解析: 把每一行与每一列当做二分图两边的点. 某格子有障碍,则对应行与列连边. ...
- 实体类与实体DTO类之间的转换
实体类与实体DTO类之间的转换 实体类与实体DTO类之间的转换 1.通过使用第三方序列化反序列化工具Newtonsoft.Json 2.通过反射实现 3.通过表达式目录树加字典缓存实现 4. 通过表达 ...
- 第18章:MYSQL分区
第18章:分区 目录 18.1. MySQL中的分区概述 18.2. 分区类型 18.2.1. RANGE分区 18.2.2. LIST分区 18.2.3. HASH分区 18.2.4. KEY分区 ...
- eclipse 修改Java代码 不用重新启动tomcat
例子: 1.在tomcat server.xml文件配置加上这句话: <Context debug="0" docBase="C:\Users\admin\Desk ...
- Java实验——输出二维数组连续二维子数组的最大和
该算法思路,根据我博客里面一维子数组求和的思路,可以用一个新的二维数组对该二维区域的数组进行求和,例如新的二维数组的第5个位置,就代表从1到5斜对角线的块状区域的和,即1,2,4,5这4个数的和,x个 ...
- java下XML与JSON互相转换的Utils类
原文:http://heipark.iteye.com/blog/1394844 需要json-lib-2.1-jdk15.jar和xom-1.2.5.jar,maven pom.xml如下: < ...
- Storm专题二:Storm Trident API 使用具体解释
一.概述 Storm Trident中的核心数据模型就是"Stream",也就是说,Storm Trident处理的是Stream.可是实际上Stream是被成批处理的. ...
- [IT学习]Python如何处理异常特殊字符
欢迎访问www.cnblogs.com/viphhs A byte of Python<输入与输出>一节中有一个处理回文的小例子(io_input.py).作者留了个思考题. 如何将标点去 ...