2019牛客暑期多校训练营(第四场)J free(分层图最短路/模板题)
题目链接:https://ac.nowcoder.com/acm/contest/884/J
题目大意:
给出一个无向图,每条边对应一个花费,有k次机会能让一条边的花费为0,让求s到t的最短路。
解题报告:
分层图最短路,就当是模板吧,下面给出两份AC代码。
建图大概长这样
AC代码:
1.直接暴力建图,花费空间和时间较大。
语言:C++ 代码长度:2264 运行时间: 269 ms 占用内存:121836K
1 #include<bits/stdc++.h>
2 #define numm ch-48
3 #define pd putchar(' ')
4 #define pn putchar('\n')
5 #define pb push_back
6 #define fi first
7 #define se second
8 #define fre1 freopen("1.txt","r",stdin)
9 #define fre2 freopen("3.txt","w",stdout)
10 #define bug cout<<"*******************"<<endl;
11 #define debug(args...) cout<<#args<<"->"<<args<<"\n";
12 using namespace std;
13 template <typename T>
14 void read(T &res) {
15 bool flag=false;char ch;
16 while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true);
17 for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
18 flag&&(res=-res);
19 }
20 template <typename T>
21 void write(T x) {
22 if(x<0) putchar('-'),x=-x;
23 if(x>9) write(x/10);
24 putchar(x%10+'0');
25 }
26 typedef long long ll;
27 typedef unsigned long long ull;
28 const int maxn=9003010; ///n*(k+1)
29 const int maxm=505;
30 const int mod=1e9+7;
31 const int inv2=500000004;
32 const int inf=0x3f3f3f3f;
33 const ll INF=0x3f3f3f3f3f3f3f3f;
34 const int N=32;
35 struct node {
36 int v,net,w;
37 }e[maxn<<2]; ///分层图层和层之前也有边,边*4
38 int head[maxn],dis[maxn],vis[maxn];
39 #define pr pair<int,int>
40 int S,T,cnt;
41 void add(int u,int v,int w) {
42 e[++cnt]={v,head[u],w};
43 head[u]=cnt;
44 }
45 void dijstra() {
46 priority_queue<pr,vector<pr>,greater<pr> >que;
47 memset(dis,inf,sizeof(dis));
48 que.push(make_pair(0,S));
49 dis[S]=0;
50 while(!que.empty()) {
51 int u=que.top().se;que.pop();
52 if(vis[u]) continue;
53 vis[u]=true;
54 for(int i=head[u];~i;i=e[i].net) {
55 int v=e[i].v,w=e[i].w;
56 if(!vis[v]&&dis[v]>dis[u]+w) {
57 dis[v]=dis[u]+w;
58 que.push(make_pair(dis[v],v));
59 }
60 }
61 }
62 }
63 int main()
64 {
65 // #define local
66 #ifdef local
67 fre1;
68 fre2;
69 #endif // local
70 int n,m,k;
71 memset(head,-1,sizeof(head));
72 read(n),read(m),read(S),read(T),read(k);
73 for(int i=1;i<=m;i++) {
74 int u,v,w;
75 read(u),read(v),read(w);
76 for(int j=0;j<=k;j++) {
77 add(u+j*n,v+j*n,w);
78 add(v+j*n,u+j*n,w);
79 if(j!=k) {
80 add(u+j*n,v+(j+1)*n,0);
81 add(v+j*n,u+(j+1)*n,0);
82 }
83 }
84 }
85 dijstra();
86 int minn=inf;
87 for(int i=0;i<=k;i++)
88 minn=min(minn,dis[T+i*n]);
89 write(minn);pn;
90 return 0;
91 }
2.用数组标记状态,省空间也省时间
语言:C++ 代码长度:2374 运行时间: 214 ms 占用内存:43628K
1 #include<bits/stdc++.h>
2 #define numm ch-48
3 #define pd putchar(' ')
4 #define pn putchar('\n')
5 #define pb push_back
6 #define fi first
7 #define se second
8 #define fre1 freopen("1.txt","r",stdin)
9 #define fre2 freopen("3.txt","w",stdout)
10 #define bug cout<<"*******************"<<endl;
11 #define debug(args...) cout<<#args<<"->"<<args<<"\n";
12 using namespace std;
13 template <typename T>
14 void read(T &res) {
15 bool flag=false;char ch;
16 while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true);
17 for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
18 flag&&(res=-res);
19 }
20 template <typename T>
21 void write(T x) {
22 if(x<0) putchar('-'),x=-x;
23 if(x>9) write(x/10);
24 putchar(x%10+'0');
25 }
26 typedef long long ll;
27 typedef unsigned long long ull;
28 const int maxn=3010; ///n*(k+1)
29 const int maxm=505;
30 const int mod=1e9+7;
31 const int inv2=500000004;
32 const int inf=0x3f3f3f3f;
33 const ll INF=0x3f3f3f3f3f3f3f3f;
34 const int N=32;
35 struct node {
36 int v,net,w;
37 }e[maxn<<1]; ///分层图层和层之前也有边,边*4
38 int head[maxn];
39 int dis[maxn][maxn],vis[maxn][maxn];
40 ///dis[i][k],用掉k次机会到达i点的花费
41 #define pr pair<int,int>
42 int S,T,cnt,n,k;
43 void add(int u,int v,int w) {
44 e[++cnt]={v,head[u],w};
45 head[u]=cnt;
46 }
47 void dijstra() {
48 priority_queue<pr,vector<pr>,greater<pr> >que;
49 memset(dis,inf,sizeof(dis));
50 que.push(make_pair(0,S-1));
51 dis[S][0]=0;
52 while(!que.empty()) {
53 int u=que.top().se;que.pop();
54 int c=u/n;u=u%n+1;
55 if(vis[u][c]) continue;
56 vis[u][c]=true;
57 for(int i=head[u];~i;i=e[i].net) {
58 int v=e[i].v,w=e[i].w;
59 if(!vis[v][c]&&dis[v][c]>dis[u][c]+w) { ///先不用机会到达下一顶点
60 dis[v][c]=dis[u][c]+w;
61 que.push(make_pair(dis[v][c],v-1+c*n));
62 }
63 if(c!=k&&!vis[v][c+1]&&dis[v][c+1]>dis[u][c]) {
64 dis[v][c+1]=dis[u][c];
65 que.push(make_pair(dis[v][c+1],v-1+(c+1)*n));
66 }
67 }
68 }
69 }
70 int main()
71 {
72 // #define local
73 #ifdef local
74 fre1;
75 fre2;
76 #endif // local
77 int m;
78 memset(head,-1,sizeof(head));
79 read(n),read(m),read(S),read(T),read(k);
80 for(int i=1;i<=m;i++) {
81 int u,v,w;
82 read(u),read(v),read(w);
83 add(u,v,w);
84 add(v,u,w);
85 }
86 dijstra();
87 int minn=inf;
88 for(int i=0;i<=k;i++)
89 minn=min(minn,dis[T][i]);
90 write(minn);pn;
91 return 0;
92 }
所谓人生,一半惊喜,一半遗憾