并不对劲的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 这题的话感觉 ...
随机推荐
- 复(学)习化学时突然的一个 idea
期中考试成功探底...但是某些化学问题还是很有信息学价值的... n 烷同分异构体计数. 这个题 fanhq666 出过,就是一个 dp. 设 f[i] 表示含有 i 个节点的无标号不同构的度数限制为 ...
- bzoj 1503[NOI 2004] 郁闷的出纳员
题目大意: 给4种操作 I:添加一个员工工资信息 A:增加所有员工的工资 S:减少所有员工的工资 F:询问工资第k高的员工的工资情况 自己做的第一道splay树的题目,初学找找感觉 #include ...
- HH的项链(codevs 2307)
题目描述 Description HH有一串由各种漂亮的贝壳组成的项链.HH相信不同的贝壳会带来好运,所以每次散步完后,他都会随意取出一段贝壳,思考它们所表达的含义.HH不断地收集新的贝壳,因此,他的 ...
- 解决ssh无操作自动断开[转载,已经验证]
用SSH远程,如果几分钟没有任何操作,连接就会断开,必须重新登陆才行,非常麻烦,一般修改2个地方3项即可解决问题: 1.终端键入:echo $TMOUT 如果显示空白,表示没有设置,等于使 ...
- vagrant的学习 之 优化
vagrant的学习 之 优化 一.修改虚拟机名字: 默认的虚拟机的名字很长:study_default_1535505004652_97747. (1)打开Vagrantfile文件:(2)找到: ...
- FLEX中restrict限定TextInput输入
restrict限制的意思 1. 限制某个字符的输入,用符号 ^ 跟上要限制的字符,可跟多个字符 <!-- 限制字符"~"的输入 --> <mx:TextInp ...
- Ubuntu 16.04关闭Alt+鼠标左键移动窗口(转)
1.打开终端,菜单-编辑-配置文件首选项-命令,勾上“以登录Shell方式运行命令”,重启终端. 2.在终端输入 gsettings get org.gnome.desktop.wm.preferen ...
- 【OPPO主题制作系列 - 01】-- 写个小工具自动打包Theme文件
参考OPPO主题设计师站: http://dev.theme.oppomobile.com/user/user_start 想要打包成Theme文件,必须把需要打包的文件夹拖到oppo-themepa ...
- linux是类unix操作系统
linux是类unix操作系统,linux与unix使用的基础命令是一样的,没有区别.Linux是一套免费使用和自由传播的类Unix操作系统,是一个基于POSIX和UNIX的多用户.多任务.支持多线程 ...
- iOS国际化:NSLocalizedString的使用
因为iOS和XCode版本号更新得太快的原因,导致网上非常多文章都失去了时效性,或许再过两三个月我这篇文章也将走上这条路,但起码能够让现阶段看到的人对iOS的国际化有个比較清楚的认识. NSLocal ...