BZOJ3832Rally题解
2024-10-08 01:18:40
一道思维神题....
我们像网络流一样加入原点S,与汇点T
用f[i]表示原点到i的最长路,用g[i]表示i到汇点的最长路
f数组与g数组都可以dp求出来的
接下来考虑如何通过这些信息来维护删除某个点的最长路
用拓扑序来删点
我们先将所有g数组加入一个集合中,
每次删点是就先将所有该点的入边的点的f[i]+g[x]从集合中删掉
然后此时集合中最大值就是删除这个点的最优解
然后再将每个点的出边i的f[x]+g[i]加入集合中
可以发现这个集合可以用堆来维护
# include<iostream>
# include<cstdio>
# include<cmath>
# include<cstring>
# include<algorithm>
# include<queue>
using namespace std;
const int mn = ;
struct Grap{
struct edge{int to,next;};
edge e[mn*];
int head[mn],edge_max;
void add(int x,int y)
{
e[++edge_max].to=y;
e[edge_max].next=head[x];
head[x]=edge_max;
}
}A,B;
int deg[mn*],n,m,a[mn*];
int f[mn*],g[mn*];
void topolpgy()
{
int tail=,head=;
for(int i=;i<=n;i++)
if(!deg[i]) a[++head]=i;
//printf("%d %d\n",tail,head);
while(tail<=head)
{
int u=a[tail];
tail++;
for(int i=A.head[u];i;i=A.e[i].next)
{
deg[A.e[i].to]--;
if(!deg[A.e[i].to]) a[++head]=A.e[i].to;
}
}
}
struct Heap{
int heap[mn*],mark[mn*],top;
void ins(int x)
{
if(mark[x])
{
--mark[x];
return ;
}
heap[++top]=x;
int t=top;
while(t>)
{
if(heap[t]>heap[t>>])
swap(heap[t],heap[t>>]),t>>=;
else
break;
}
}
void del(int x)
{
mark[x]++;
}
void Pop()
{
heap[]=heap[top--];
int t=;
while(t<=top)
{
if( t<top && heap[t+]>heap[t] )
t++;
if(heap[t]>heap[t>>])
swap(heap[t],heap[t>>]),t<<=;
else
break;
}
}
int Top()
{
while(mark[heap[]])
mark[heap[]]--,Pop();
return heap[];
}
}T;
int main()
{
int x,y;
A.edge_max=,B.edge_max=;
scanf("%d%d",&n,&m);
for(int i=;i<=m;i++)
{
scanf("%d%d",&x,&y);
A.add(x,y),B.add(y,x);
deg[y]++;
}
topolpgy();
/*for(int i=1;i<=n;i++)
printf("%d ",a[i]);*/
int ans=,ans_len=0x3f3f3f3f;
for(int i=;i<=n;i++)
{
int u=a[i];
f[u]=max(f[u],);
for(int j=A.head[u];j;j=A.e[j].next)
f[A.e[j].to]=max(f[A.e[j].to],f[u]+);
}
for(int i=n;i>=;i--)
{
int u=a[i];
g[u]=max(g[u],);
for(int j=A.head[u];j;j=A.e[j].next)
g[u]=max(g[u],g[A.e[j].to]+);
}
/*for(int i=1;i<=n;i++)
printf("%d:%d %d\n",i,f[i],g[i]);*/
for(int i=;i<=n;i++)
T.ins(g[i]);
T.ins();
for(int i=;i<=n;i++)
{
int u=a[i];
for(int j=B.head[u];j;j=B.e[j].next)
{
T.del(f[B.e[j].to]+g[u]);
//printf("%d ",f[B.e[j].to]+g[u]);
}
//printf("\n");
T.del(g[u]);
if(T.Top()<ans_len)
{
ans_len=T.Top(),ans=u;
//printf("%d ",T.Top());
}
for(int j=A.head[u];j;j=A.e[j].next)
{
T.ins(f[u]+g[A.e[j].to]);
//printf("%d ",f[u]+g[B.e[j].to]);
}
T.ins(f[u]);
//printf("%d\n",ans_len-1);
}
printf("%d %d",ans,ans_len-);
return ;
}
最新文章
- windows 共享文件夹 给 mac
- python基础之day1
- 1.0、Struts2的简单搭建方法
- MAC下彻底解决mysql无法插入和显示中文
- MFC程序执行顺序 .
- 强大的Spring缓存技术(中)
- Android 热补丁和热修复
- 基础知识系列☞GET和POST→及相关知识
- C#中messagebox用法
- hdu 5067 Harry And Dig Machine
- mysql语句在node.js中的写法
- [2017-07-18]logstash配置示例
- WPF 完美截图 <;二>;
- 用nodejs实现简单爬虫
- 红米手机4A怎么样刷入开发版获得ROOT权限
- Loadrunner学习资料
- LockSupport浅析
- python模块之random
- Spark基本架构及原理
- 【python38--面向对象继承】