题目大意
有张n个点,m条边的图,设dis[i]为1到i的最短路径。
第i次修改,将某条边的边权从1变成2。
求i次修改后,有多少个i的dis[i]变了。
题解
考虑最短路是怎么一步步求出来的。
考虑最经典的spfa。
最后能够搞出一个拓扑图。(比赛的时候一条拓扑图的边被计算很多很多次)
在拓扑图上不考虑删边,而是给边赋权。
那么一个点i的dis[i]最后什么时候改变?这个时间就是从1到i所有拓扑序列的路径权值的最大值。
定义路径权值:这条路径的边的最小权值。
直接拓扑排序即可。
危险信息
DIJ+堆优化打错了。必须找出原因。
代码
#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
#define N 100010
#define M 200010
#define P(a) putchar(a)
#define Max(x,y) ((x)>(y)?(x):(y))
#define Min(x,y) ((x)<(y)?(x):(y))
#define fo(i,a,b) for(i=a;i<=b;i++)
using namespace std;
struct note{
int to,next,id;
}edge[M<<1],edge1[M<<1];
int p[M];
int head[N],tot;
int head1[N],tot1;
int dis[N],dis1[N];
int n,m,q,i,j,k,ans[M];
int qu[N*10],ql,qr,COL;
int u,v,wz,xin;
int weight[M],outd[N];
int bz[N];
bool bz1[M];
int read(){
int fh=0,rs=0;char ch=0;
while((ch<'0'||ch>'9')&&(ch^'-'))ch=getchar();
if(ch=='-')fh=1,ch=getchar();
while(ch>='0'&&ch<='9')rs=(rs<<3)+(rs<<1)+(ch^'0'),ch=getchar();
return fh?-rs:rs;
}
void write(int x){
if(x>9)write(x/10);
P(x%10+'0');
}
void lb1(int x,int y,int z){
edge1[++tot1].to=y;
edge1[tot1].next=head1[x];
edge1[tot1].id=z;
head1[x]=tot1;
}
void lb(int x,int y,int z){
edge[++tot].to=y;
edge[tot].next=head[x];
edge[tot].id=z;
head[x]=tot;
}
void spfa0(){
int i,x,w;
dis[1]=0;
fo(i,2,n)dis[i]=2139062143;
qr=1,ql=0;
qu[1]=1;
while(ql<qr){
x=qu[++ql];
for(i=head[x];i;i=edge[i].next){
if(dis[edge[i].to]>dis[x]+1){
dis[edge[i].to]=dis[x]+1;
qu[++qr]=edge[i].to;
}
}
}
}
void sou(){
int i,x;
fo(x,1,n){
for(i=head[x];i;i=edge[i].next)
if(dis[edge[i].to]==dis[x]+1){
bz1[edge[i].id]=1;
lb1(x,edge[i].to,edge[i].id);
outd[edge[i].to]++;
}
}
}
void dye(){
int i,x;
qu[qr=1]=1;ql=0;
bz[1]=COL;
xin=1;
while(ql<qr){
x=qu[++ql];
for(i=head1[x];i;i=edge1[i].next)
if(bz1[edge1[i].id]&&(bz[edge1[i].to]^COL)){
qu[++qr]=edge1[i].to;
bz[edge1[i].to]=COL;
xin++;
}
}
}
int main(){
n=read();m=read();q=read();
fo(i,1,m){
u=read(),v=read();
lb(u,v,i);lb(v,u,i);
weight[i]=2139062143;
}
fo(i,1,q)p[i]=read();
spfa0();
fo(i,1,n)bz[i]=0;
sou();
fo(i,1,q)weight[p[i]]=i;
qu[qr=1]=1,ql=0;
dis1[1]=q+1;
while(ql<qr){
u=qu[++ql];
for(i=head1[u];i;i=edge1[i].next){
outd[edge1[i].to]--;
dis1[edge1[i].to]=Max(dis1[edge1[i].to],Min(dis1[u],weight[edge1[i].id]));
if(!outd[edge1[i].to]){
qu[++qr]=edge1[i].to;
}
}
}
sort(dis1+1,dis1+n+1);
fo(i,1,n){
ans[dis1[i]]=ans[dis1[i-1]]+1;
}
fo(i,1,q)ans[i]=Max(ans[i],ans[i-1]);
fo(i,1,q)write(ans[i]),P('\n');
return 0;
}

被折叠的 条评论
为什么被折叠?



