Mw Winter Camp Day4 DivB E(bfs+卡常)

题意

给定 $n$ 个点 $m$ 条边的图 $(n\le900,m\le150000)$ ,问去掉每条边 $\lt x,y\gt$ 之后,$x$ 到 $y$ 最短路,边权均为 $1$

题解

考虑 $u$ 的最短路径树,去掉边 $$ 之后只影响被边 $$ 支配的点,初步确定是 $v$ 的子树,此时到 $v$ 的最短距离无非是从其他子树转移过来,所以可以对 $v$ 的子树反向做 $bfs$ ,然后枚举从其他子树过渡到该子树的边就可以了。。复杂度为 $O(nm)$

复杂度还是比较危险的,事实上也 $T$ 了,需要卡卡常。。

  • 答案为 $2$ 可以直接 $break$ (对稠密图非常有效)
  • 加读入优化和 $inline$
  • 要通过各种姿势把 $bfs$ 的次数卡在 $2$ 次以内
  • 打标记避免重复入队(即使只有 $2$ 次。。)

其他的优化方法也不太记得了,这个代码估计也是在 $TLE$ 的边缘大鹏展翅,去了 $inline$ 就 $T$ 的那种。。

少有的卡常体验,一直卡常一直爽~~




代码

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
/**
*         ┏┓    ┏┓
*         ┏┛┗━━━━━━━┛┗━━━┓
*         ┃       ┃  
*         ┃   ━    ┃
*         ┃ >   < ┃
*         ┃       ┃
*         ┃... ⌒ ...  ┃
*         ┃ ┃
*         ┗━┓ ┏━┛
*          ┃ ┃ Code is far away from bug with the animal protecting          
*          ┃ ┃ 神兽保佑,代码无bug
*          ┃ ┃           
*          ┃ ┃       
*          ┃ ┃
*          ┃ ┃           
*          ┃ ┗━━━┓
*          ┃ ┣┓
*          ┃ ┏┛
*          ┗┓┓┏━━━━━━━━┳┓┏┛
*           ┃┫┫ ┃┫┫
*           ┗┻┛ ┗┻┛
*/

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<queue>
#include<map>
#include<stack>
#include<cmath>
#include<set>
#include<bitset>
#include<assert.h>
#define inc(i,l,r) for(int i=l;i<=r;i++)
#define dec(i,l,r) for(int i=l;i>=r;i--)
#define link(x) for(edge *j=h[x];j;j=j->next)
#define mem(a) memset(a,0,sizeof(a))
#define ll long long
#define eps 1e-6
#define succ(x) (1<<x)
#define lowbit(x) (x&(-x))
#define sqr(x) ((x)*(x))
#define mid (x+y)/2
#define NM 905
#define nm 170005
#define pi 3.1415926535897931
const int inf=1e9+7;
using namespace std;
inline int read(){
int x=0,f=1;char ch=getchar();
while(!isdigit(ch)){if(ch=='-')f=-1;ch=getchar();}
while(isdigit(ch))x=x*10+ch-'0',ch=getchar();
return f*x;
}






int d[NM],_d[NM],v[NM],n,m,_x,_y;
bool _v[NM];
int ans[nm];
queue<int>q;
struct edge{int t,v;edge*next;}e[2*nm],*h[NM],*o=e,*_h[NM];
inline void add(int x,int y,int v){o->v=v;o->t=y;o->next=h[x];h[x]=o++;}
inline void _add(int x,int y){o->t=y;o->next=_h[x];_h[x]=o++;}
#define _link(x) for(edge*j=_h[x];j;j=j->next)


inline int bfs(int u){
int ans=inf;
q.push(u);_d[u]=0;
while(!q.empty()){
int t=q.front();q.pop();
_link(t)if(v[j->t]==u){
if(_d[j->t]==inf)_d[j->t]=_d[t]+1,q.push(j->t);
}else if(d[j->t]){ans=min(ans,d[j->t]+_d[t]+1);if(ans==2)break;}
if(ans==2)break;
}
while(!q.empty())q.pop();
return ans;
}


int main(){
//freopen("data.in","r",stdin);
while(~scanf("%d%d",&n,&m)&&n&&m){
inc(i,1,n)_h[i]=h[i]=0;o=e;
inc(i,1,m){_x=read();_y=read();add(_x,_y,i);_add(_y,_x);}
inc(i,1,n){
inc(j,1,n)d[j]=_d[j]=inf,v[j]=0;
link(i)q.push(j->t),d[j->t]=1,v[j->t]=j->t,_v[j->t]++;
d[i]=0;v[i]=-1;
while(!q.empty()){
int t=q.front();q.pop();_v[t]=false;
link(t)if(!v[j->t])v[j->t]=v[t],d[j->t]=d[t]+1,q.push(j->t),_v[j->t]++;
else if(v[j->t]>0&&v[j->t]!=v[t]&&d[j->t]==d[t]+1){
if(!_v[j->t])q.push(j->t);
v[j->t]=-1;
}
}
link(i)ans[j->v]=bfs(j->t);
}
inc(i,1,m)if(ans[i]<inf)printf("%d ",ans[i]);else printf("0 ");putchar('\n');
}
return 0;
}