題目背景
本題開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;
}