当先锋百科网

首页 1 2 3 4 5 6 7

在这里插入图片描述
在这里插入图片描述

题解

虽然他有很多边,但是不少边都没有存在意义。
因为我们只关心最短路,所以如果一条边没有构成最短路,
那么无论他存在与否,都对最短路没有任何影响。
根据构成最短路边,造出一个最短路图,
这个图是一个有向无环图。
考虑一个点什么时候到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');
	}
}