题解
虽然他有很多边,但是不少边都没有存在意义。
因为我们只关心最短路,所以如果一条边没有构成最短路,
那么无论他存在与否,都对最短路没有任何影响。
根据构成最短路边,造出一个最短路图,
这个图是一个有向无环图。
考虑一个点什么时候到1号点的最短路改变,
显然是它的入度变为了0,
当它不再与1连通,那么它连出去的边也就不是构成最短路的边了,
也应该删去。
思考这个过程,是不是很像拓扑序呢。
code
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
char ch;
void read(int&n)
{
for(ch=getchar();ch<'0' || ch>'9';ch=getchar());
for(n=0;'0'<=ch && ch<='9';ch=getchar())n=(n<<1)+(n<<3)+ch-48;
}
void write(int x){if(x>9)write(x/10);putchar(x%10+48);}
const int N=1000003;
int n,m,q,x[N*2],y[N*2],d[N],dis[N],r[N*2],f[N],ans;
int xx,yy,id[N*4],nxt[N*4],to[N*4],lst[N],tot,head,tail;
bool p[N*2];
void ins(int x,int y)
{
nxt[++tot]=lst[x];
to[tot]=y;lst[x]=tot;
}
int get(int x){return f[x]=((f[x]^x)?get(f[x]):x);}
int main()
{
freopen("train.in","r",stdin);
freopen("train.out","w",stdout);
read(n);read(m);read(q);
for(int i=1;i<=m;i++)
read(x[i]),read(y[i]),ins(x[i],y[i]),ins(y[i],x[i]);
memset(dis,127,sizeof(dis));
for(d[tail=1]=dis[1]=1,head=0;head<tail;)
{
xx=d[++head];
for(int i=lst[xx];i;i=nxt[i])
if(dis[to[i]]>dis[xx]+1)dis[d[++tail]=to[i]]=dis[xx]+1;
}
memset(id,0,sizeof(id));
memset(p,1,sizeof(p));
memset(lst,0,sizeof(lst));
tot=0;f[1]=1;
for(int i=1;i<=m;i++)
{
if(dis[x[i]]-dis[y[i]]==1)ins(y[i],x[i]),id[i]=tot,f[x[i]]++;
if(dis[y[i]]-dis[x[i]]==1)ins(x[i],y[i]),id[i]=tot,f[y[i]]++;
}
for(int i=1;i<=q;i++)
{
read(xx);
if(id[xx]==0)
{
write(ans),putchar('\n');
continue;
}
if(p[id[xx]])
{
p[id[xx]]=0;
f[yy=to[id[xx]]]--;
if(f[yy]==0)
{
ans++;
for(d[tail=1]=yy,head=0;head<tail;)
{
xx=d[++head];
for(int j=lst[xx];j;j=nxt[j])
if(p[j])
{
p[j]=0;f[to[j]]--;
if(f[to[j]]==0)ans++,d[++tail]=to[j];
}
}
}
}
write(ans),putchar('\n');
}
}