JZOJ5959. 【NOIP2018模拟11.8A组】铁路运输

14 篇文章 0 订阅
1 篇文章 0 订阅

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

题解

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

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值