题解:P8860 动态图连通性
文章将同步在博客园发表。
题面
转化题。
首先显然无法在线做,不然就真的成动态图连通性了。
我们假设第
-
路径上最小的
d 尽可能大。 -
在满足条件一的情况下,路径上第二小的
d 尽可能大。 -
在满足条件一、二的情况下,路径上第三小的
d 尽可能大。
依次类推。
其实就是把路径上的
现在的问题就是如何找到这条路。
在这之前我们先考虑一下别的情况:
如果同一条边被删除了多次,那么显然我们以第一次删除的时间为准,后面的删除操作的答案显然都是
回到找路径这里。因为每个
显然我可以把
此时上面的条件就被我们转化为最短路问题。我们考虑怎么做这个最短路问题。
显然你如果加一个
但是可持久化线段树实现稍微有点复杂,所以我们来观察性质。
我们考虑两个点
-
假设
dis_{st_1}<dis_{st_2} ,显然我们可以将条件反过来,结果是一样的。 -
那么根据 Dijkstra 的特性,因为
st_2 在ed 之前被取出来,所以有dis_{st_1}+10^{q-d_1}>dis_{st_2} 。 -
又因为每个
d 只出现过一次,所以dis_{st_1} 和dis_{st_2} 在q-d_1 这一位的数字都是0 。 -
所以我们可以知道
dis_{st_1} 和dis_{st_2} 应该长这样:在q-d_1 位及之前都一样且第q-d_1 位为0 ,在q-d_1 为后面的随意但是保证dis_{st_2}>dis_{st_1} 。
现在我们考虑
因此我们直接将第一维改为
代码:
const int N=2e5+6;
struct edge{
int x,y;
}e[N];
int n,m,q,d[N],la[N];
bool ans[N],vis[N];
vector<int>v[N];
signed main()
{
n=read(),m=read(),q=read();
for(int i=1,x,y;i<=m;i++)
{
x=read(),y=read();
e[i]=(edge){x,y};
v[x].push_back(i);
d[i]=q+1;
}
for(int i=1;i<=q;i++)
{
int x=read();
if(d[x]>q)
{
d[x]=i;
ans[i]=true;
}
else
{
ans[i]=false;
}
}
priority_queue<pair<int,int>>pq;
pq.push(make_pair(0,m+1));
e[m+1].y=1;
while(!pq.empty())
{
pair<int,int>p=pq.top();
pq.pop();
int x=e[p.second].y;
if(vis[x])
{
continue;
}
vis[x]=1;
la[x]=p.second;
for(auto i:v[x])
{
pq.push(make_pair(d[i],i));
}
}
for(int i=n;i;i=e[la[i]].x)
{
ans[d[la[i]]]=false;
}
for(int i=1;i<=q;i++)
{
write(ans[i]?1:0);
putchar('\n');
}
return 0;
}