题目背景
本题开O2优化,请注意常数
题目描述
博艾市除了有海底高铁连接中国大陆、台湾与日本,市区里也有很成熟的轨道交通系统。我们可以认为博艾地铁系统是一个无向连通图。博艾有N个地铁站,同时有M小段地铁连接两个不同的站。
地铁计价方式很简单。从A站到B站,每经过一小段铁路(连接直接相邻的两个点的一条边),就要收取1博艾元。也就是说,从A站到B站,选择的路径不一样,要价也会不同。
我们认为凡华中学在1号地铁站。学生们通过地铁通勤,他们当然知道选择最短路来坐车的话,票价最便宜。
然而博艾地铁公司经营不善,一直亏损,于是他们打算提价。提价一次就是将一小段铁路原来收费1元改收2元。同一小段的铁路不会多次提价。他们打算提价Q次。
学生们知道,如果他们到学校的一条最短路径中的一小段提价了,可以改变路径,使总票价不变。然而随着一条一条的铁路被提价,当居住在某个站附近的学生发现,提价后,没有任何一种方案可以从家到学校的费用和初始费用相等时,就会不满。
现在地铁公司希望知道,对于每一次涨价,有多少个站,学生会因为涨价而不满呢?
输入输出格式
输入格式:第一行为三个整数N,M,Q。
接下来M行,每行2个整数ai,bi,表示第i条铁路连接的两个站。i表示铁路编号。
接下来Q行,每行一行整数rj,表示每次涨价的铁路编号。
输出格式:Q行。每行一个整数表示不满的车站数量。
输入输出样例
5 6 5 1 2 1 3 4 2 3 2 2 5 5 3 5 2 4 1 3
0 2 2 4 4
说明
【样例解释】
次数 车站2 车站3 车站4 车站5
初始 1 1 2 2
1 1 1 2 2
2 1 2 2 3
3 1 2 2 3
4 2 2 3 3
5 2 2 4 3
【数据范围】
对于20%的数据 N≤100, Q≤30
对于40%的数据 Q≤30
对于70%的数据 正确的输出结果中,不会有超过50种不一样的整数(数据范围剧透解法系列)
对于100%的数据 N≤100000, Q≤M≤200000
既然开了O2...那么就玩一玩stl... 数组开小了一开始。 害老子白bat了一个小时。。
不是很懂为什么网上题解都要倒过来做。。。首先对于每一次涨价。。就是相当于删边,设e[1]=x,e[2]=y; 若abs(dis[x]-dis[y])!=1 那么这条边本来就不在我们构好的层级图里也就不用操作了。我们在bfs构造层级图的时候记录一下每个点像这样有意义的入度每次删到有意义的边的时候就ru[y]--;当ru[y]=0 那么此时y就不满了。同时y之后的一些节点也有不满的可能,我们就继续dfs下去。
#include <cstdio>
#include <cmath>
#include <ctime>
#include <string>
#include <cstring>
#include <cstdlib>
#include <iostream>
#include <algorithm>
#include<set>
#include <vector>
#include<queue>
#define pb push_back
#define forup(i,a,b) for(int i=(a);i<=(b);i++)
#define fordown(i,a,b) for(int i=(a);i>=(b);i--)
#define maxn 200005
#define maxm 100005
#define INF 1070000000
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
template<class T> inline
void read(T& num){ num = 0; bool f = true;char ch = getchar(); while(ch < '0' || ch > '9') { if(ch == '-') f = false;ch = getchar();} while(ch >= '0' && ch <= '9') {num = num * 10 + ch - '0';ch = getchar();} num = f ? num: -num; }
int out[100];
template<class T> inline
void write(T x,char ch){ if (x==0) {putchar('0'); putchar(ch); return;} if (x<0) {putchar('-'); x=-x;}int num=0; while (x){ out[num++]=(x%10); x=x/10;} fordown(i,num-1,0) putchar(out[i]+'0'); putchar(ch); }
/*==================split line==================*/
int n,m,Q;
bool flag[maxn];
int e[maxn][2];
int dis[maxn];
vector<int> g[maxn];
bool vis[maxn];
multiset<int> G[maxn];
int ru[maxn];
int ans=0;
void dfs(int x)
{ for(int i=0;i<g[x].size();i++)
{ int u=g[x][i];
if(dis[u]==dis[x]+1)
{ G[x].insert(u),ru[u]++; if(vis[u]==0) vis[u]=1,dfs(u);}}}
void bfs()
{ queue<int> q;q.push(1);vis[1]=1;dis[1]=0;
while(!q.empty())
{ int x=q.front();q.pop();
for(int i=0;i<g[x].size();i++) { int u=g[x][i]; if(!vis[u]) vis[u]=1,dis[u]=1+dis[x],q.push(u); }
}
}
void solve(int x)
{//cout<<G[x].size()<<endl;
for(multiset<int>::iterator i=G[x].begin();i!=G[x].end();)//遍历连出去的每个点
{ int u=*i;
if(!flag[u])
{G[x].erase(i++);ru[u]--;
if(ru[u]==0)
{ flag[u]=1; ans++; solve(u); }
}
else
i++;
}
}
bool v[maxn];
void query()
{int p;read(p);
if(v[p]) {write(ans,'\n');return;}
v[p]=1;
int x=e[p][1],y=e[p][0];
// if(flag[x]||flag[y]) {write(ans,'\n');return;}
if(dis[x]==dis[y]) {write(ans,'\n');return;}
if(dis[x]>dis[y]) swap(x,y);
if(G[x].find(y)!=G[x].end())
{ ru[y]--;G[x].erase(G[x].find(y));
if(ru[y]==0)
{flag[y]=1;
ans++;
solve(y);
}
}
write(ans,'\n');
}
int main()
{ freopen("map.in","r",stdin); freopen("1.out","w",stdout);
cin>>n>>m>>Q;
forup(i,1,m)
{int x,y; read(x);read(y);e[i][0]=x;e[i][1]=y; g[x].pb(y);g[y].pb(x);}
bfs();//就是你的spfa..
memset(vis,0,sizeof(vis));
vis[1]=1;
dfs(1);//重新构一个有向图
while(Q--)
query(); //做每个询问
return 0;
}