0%

ABC - 375 - F - Road Blocked

AC代码

时光倒流trick+floyd

注意重边处理

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
110
111
112
113
114
115
116
117
118
119
120
#include <iostream>
#include <cstring>
#include <algorithm>
#include <deque>
#include <queue>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <bitset>

using namespace std;
typedef long long ll;
const ll N=310,M=90100;
ll n,m,query,cnt,inf; // D里存的是到该点的最短距离(目前)
ll g[N][N],C[M];
pair<ll,ll> road[M];
vector<ll> ans; // 逆序存储答案
struct opxy {
ll op,x,y;
};
vector<opxy> opp; // 就是存一下操作,实现时光倒流

// 时光倒流trick+floyd(以每个点为中间点进行的距离dp)

inline void floyd() {
for(int i=1;i<=n;++i) {
for(int j=1;j<=n;++j) {
if(i==j)
continue;
for(int k=1;k<=n;k++) {
if(k==i)
continue;
g[j][k]=min(g[j][i]+g[i][k],g[j][k]);
}
}
}
}

inline void update(ll a,ll b) {
ll i=a;
for(int j=1;j<=n;++j) {
if(i==j)
continue;
for(int k=1;k<=n;k++) {
if(k==i)
continue;
g[j][k]=min(g[j][i]+g[i][k],g[j][k]);
}
}
i=b;
for(int j=1;j<=n;++j) { // (与上一段重复)
if(i==j)
continue;
for(int k=1;k<=n;k++) {
if(k==i)
continue;
g[j][k]=min(g[j][i]+g[i][k],g[j][k]);
}
}
}

int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m>>query;
memset(g,0x3f,sizeof(g)); // g初始化
inf=g[0][0];
for(int i=1;i<=n;++i) {
g[i][i]=0; // 自己到自己肯定距离为0
}
for(int i=1;i<=m;++i) {
ll a,b,c;
cin>>a>>b>>c;
g[a][b]=min(c,g[a][b]);
g[b][a]=min(c,g[b][a]);
road[++cnt]=make_pair(a,b);
C[cnt]=c;
}
for(int _=1;_<=query;++_) {
int op;
cin>>op;
if(op==1) {
ll idx;
cin>>idx;
ll a,b;
a=road[idx].first,b=road[idx].second;
if(g[a][b]==C[idx])
g[a][b]=inf,g[b][a]=inf; // 删边(处理重边情况)
opxy lop; lop.op=1,lop.x=idx;
opp.push_back(lop);
}else {
ll x,y;
cin>>x>>y;
opxy lop; lop.op=op,lop.x=x,lop.y=y;
opp.push_back(lop);
}
}
floyd();
for(int i=opp.size()-1;i>=0;--i) { // 哈哈,时光倒流启动!!!
ll op=opp[i].op,x=opp[i].x,y=opp[i].y;
if(op==1) {
ll a=road[x].first,b=road[x].second;
g[a][b]=min(C[x],g[a][b]),g[b][a]=min(C[x],g[b][a]);
update(a,b);
}else {
if(g[x][y]!=inf)
ans.push_back(g[x][y]);
else
ans.push_back(-1);
}
}
for(int i=ans.size()-1;i>=0;--i) {
cout<<ans[i]<<endl;
}
}
//不知道为什么RE了好几个 https://atcoder.jp/contests/abc375/submissions/59448981
// WA 未处理重边 https://atcoder.jp/contests/abc375/submissions/59449001
// 处理了一下重边 AC https://atcoder.jp/contests/abc375/submissions/59449193

心路历程(WA,TLE,MLE……)

能跑,但是TLE,我发现这题竟然是floyd算法

需要时光倒流trick+floyd

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
#include <iostream>
#include <cstring>
#include <algorithm>
#include <deque>
#include <queue>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <bitset>

using namespace std;
typedef long long ll;
const ll N=310,M=9010;
ll n,m,query,cnt,D[N],inf; // D里存的是到该点的最短距离(目前)
vector<pair<ll,ll> > g[N];
pair<ll,ll> road[9010];
bool ban[N][N];
bitset<N> done; // 存的就是dij当中已经确定的点
struct cmp {
bool operator()(pair<ll,ll> a,pair<ll,ll> b) {
if(a.second!=b.second)
return a.second>b.second; // 我们需要一个小根堆,second是存的边的长度
return false;
}
};
inline ll solve(ll x,ll y) {
priority_queue<pair<ll,ll>,vector<pair<ll,ll> >, cmp> q;
D[x]=0;
q.push(make_pair(x,0));
while (!q.empty()) {
ll cdis=q.top().second,cn=q.top().first;
q.pop();
if(done[cn]) // 这种写法是可能会有冗余,故要判断一下
continue;
done[cn]=true;
D[cn]=cdis;
if(done[y])
return D[y];
for(int i=0;i<g[cn].size();i++) {
ll fn=g[cn][i].first,fdis=g[cn][i].second+cdis;
if(ban[cn][fn])
continue;
q.push(make_pair(fn,fdis));
}
}
if(D[y]==inf)
return -1;
return D[y];
}

int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m>>query;
for(int i=1;i<=m;i++) {
ll a,b,c;
cin>>a>>b>>c;
g[a].push_back(make_pair(b,c));
g[b].push_back(make_pair(a,c));
road[++cnt]=make_pair(a,b);
}
for(int _=1;_<=query;_++) {
int op;
cin>>op;
if(op==1) {
ll idx;
cin>>idx;
ll a=road[idx].first,b=road[idx].second;
ban[a][b]=true;ban[b][a]=true;
}else {
ll x,y;
cin>>x>>y;
memset(D,0x3f,sizeof(D));
inf=D[0];
done.reset();
cout<<solve(x,y)<<endl;
}
}
}

WA了,可能是没有判别重边

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
110
111
112
113
114
115
116
117
#include <iostream>
#include <cstring>
#include <algorithm>
#include <deque>
#include <queue>
#include <vector>
#include <set>
#include <map>
#include <cmath>
#include <bitset>

using namespace std;
typedef long long ll;
const ll N=310,M=90100;
ll n,m,query,cnt,inf; // D里存的是到该点的最短距离(目前)
ll g[N][N],C[M];
pair<ll,ll> road[M];
vector<ll> ans; // 逆序存储答案
struct opxy {
ll op,x,y;
};
vector<opxy> opp; // 就是存一下操作,实现时光倒流

// 时光倒流trick+floyd(以每个点为中间点进行的距离dp)

inline void floyd() {
for(int i=1;i<=n;++i) {
for(int j=1;j<=n;++j) {
if(i==j)
continue;
for(int k=1;k<=n;k++) {
if(k==i)
continue;
g[j][k]=min(g[j][i]+g[i][k],g[j][k]);
}
}
}
}

inline void update(ll a,ll b) {
ll i=a;
for(int j=1;j<=n;++j) {
if(i==j)
continue;
for(int k=1;k<=n;k++) {
if(k==i)
continue;
g[j][k]=min(g[j][i]+g[i][k],g[j][k]);
}
}
i=b;
for(int j=1;j<=n;++j) { // (与上一段重复)
if(i==j)
continue;
for(int k=1;k<=n;k++) {
if(k==i)
continue;
g[j][k]=min(g[j][i]+g[i][k],g[j][k]);
}
}
}

int main()
{
ios::sync_with_stdio(false);
cin.tie(0);cout.tie(0);
cin>>n>>m>>query;
memset(g,0x3f,sizeof(g)); // g初始化
inf=g[0][0];
for(int i=1;i<=n;++i) {
g[i][i]=0; // 自己到自己肯定距离为0
}
for(int i=1;i<=m;++i) {
ll a,b,c;
cin>>a>>b>>c;
g[a][b]=c;
g[b][a]=c;
road[++cnt]=make_pair(a,b);
C[cnt]=c;
}
for(int _=1;_<=query;++_) {
int op;
cin>>op;
if(op==1) {
ll idx;
cin>>idx;
ll a,b;
a=road[idx].first,b=road[idx].second;
g[a][b]=inf,g[b][a]=inf; // 删边
opxy lop; lop.op=1,lop.x=idx;
opp.push_back(lop);
}else {
ll x,y;
cin>>x>>y;
opxy lop; lop.op=op,lop.x=x,lop.y=y;
opp.push_back(lop);
}
}
floyd();
for(int i=opp.size()-1;i>=0;--i) { // 哈哈,时光倒流启动!!!
ll op=opp[i].op,x=opp[i].x,y=opp[i].y;
if(op==1) {
ll a=road[x].first,b=road[x].second;
g[a][b]=C[x],g[b][a]=C[x];
update(a,b);
}else {
if(g[x][y]!=inf)
ans.push_back(g[x][y]);
else
ans.push_back(-1);
}
}
for(int i=ans.size()-1;i>=0;--i) {
cout<<ans[i]<<endl;
}
}
//不知道为什么RE了好几个 https://atcoder.jp/contests/abc375/submissions/59448981