Sorry, your browser cannot access this site
This page requires browser support (enable) JavaScript
Learn more >

GCSG01's Blogs

Welecome to my blog.A place to share my thoughts and experiences.

对于一些有限制次数的改变图上的边的题目,将原图复制若干份,也就是若干层,每层之间用特殊的边(题目给出的条件)连接起来,然后再跑最短路。

1.P4568 [JLOI2011] 飞行路线

$k$ 条航线,我们便在原图的基础上再建立 $k$ 张子图,共 $k+1$ 张图,题目给出的特殊条件为转换边权使得其为 $0$,所以对于一条边 $(u,v,w)$,我们需要在第 $i、i+1$ 张图之间连一条 $(u_i,v_i+1,0)$ 的边,表示可以用一次机会使得该边边权变为 $0$。图建完后,再跑一边最短路统计答案即可,注意 $k$ 次机会不一定全部用完。

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
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=1e4+5,K=15;
struct node{
int v,w;
};
vector<node>a[N*K];
int dis[N*K],f[N*K];
int n,m,k,s,t;
struct cmp{
bool operator ()(const node &A,const node &B)
{
return A.w>B.w;
}
};
void dij()
{
memset(dis,0x3f,sizeof(dis));
dis[s]=0;
priority_queue<node,vector<node>,cmp>q;
q.push((node){s,0});
while(!q.empty())
{
node now=q.top();q.pop();
int u=now.v;
if(f[u])continue;
f[u]=1;
for(int i=0;i<a[u].size();i++)
{
int v=a[u][i].v,w=a[u][i].w;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
if(!f[v])q.push((node){v,dis[v]});
}
}
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m>>k>>s>>t;
s++,t++;
for(int i=1;i<=m;i++)
{
int u,v,w;
cin>>u>>v>>w;
u++,v++;
for(int j=0;j<=k;j++)
{
int uu=j*n+u,vv=j*n+v;
a[uu].push_back((node){vv,w});
a[vv].push_back((node){uu,w});
if(j!=k)
a[uu].push_back((node){vv+n,0}),
a[vv].push_back((node){uu+n,0});
}
}
dij();
int ans=INT_MAX;
for(int i=0;i<=k;i++)
ans=min(ans,dis[i*n+t]);
cout<<ans;
return 0;
}

2.[ABC277E] Crystal Switches

考虑将初始可走与初始不可走的边分层,将有开关的点在两层之间连一条边权为 $0$ 的边,跑最短路。

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
#include<bits/stdc++.h>
#define int long long
using namespace std;
const int N=5e5+5;
struct node{
int v,w;
};
vector<node>a[N];
int dis[N],f[N];
int n,m,k,s=1,t;
struct cmp{
bool operator ()(const node &A,const node &B)
{
return A.w>B.w;
}
};
void dij()
{
memset(dis,0x3f,sizeof(dis));
dis[s]=0;
priority_queue<node,vector<node>,cmp>q;
q.push((node){s,0});
while(!q.empty())
{
node now=q.top();q.pop();
int u=now.v;
if(f[u])continue;
f[u]=1;
for(int i=0;i<a[u].size();i++)
{
int v=a[u][i].v,w=a[u][i].w;
if(dis[v]>dis[u]+w)
{
dis[v]=dis[u]+w;
if(!f[v])q.push((node){v,dis[v]});
}
}
}
}
signed main()
{
ios::sync_with_stdio(0);
cin.tie(0);cout.tie(0);
cin>>n>>m>>k;
for(int i=1;i<=m;i++)
{
int u,v,w;
cin>>u>>v>>w;
if(!w)u+=n,v+=n;
a[u].push_back((node){v,1});
a[v].push_back((node){u,1});
}
for(int i=1;i<=k;i++)
{
int x;
cin>>x;
a[x].push_back((node){x+n,0});
a[x+n].push_back((node){x,0});
}
dij();
int ans=min(dis[n],dis[n*2]);
if(ans>INT_MAX)cout<<"-1";
else cout<<ans;
return 0;
}

习题:
P4822 [BJWC2012] 冻结
P2939 [USACO09FEB] Revamping Trails G
P3119 [USACO15JAN] Grass Cownoisseur G

评论