【Acwing—单源最短路:建图】
创始人
2024-02-01 20:34:58
0

y总说,图论题的难点不在于打板子,而是建图的过程

个人觉得,建图的过程分成以下阶段:

1.确定结点的意义

2.确定边权的意义

结点一般都很显然,但是边权的意义我们一般把它设成对答案(或需要维护的东西)的贡献

具体看以下的例子:

1.热浪

1129. 热浪 - AcWing题库

题意:

思路:

跑一遍最短路就行,spfa,dij,floyd都行

Code:

#include 
using namespace std;
const int mxn=1e4+10,mxe=1e4+10,mnf=0x3f3f3f3f;
struct ty{int to,next,w;
}edge[mxe<<1];
queue q;
int n,m,s,t,u,v,w,tot=0;
int head[mxn],dis[mxn],vis[mxn];
void add(int u,int v,int w){edge[tot].w=w;edge[tot].to=v;edge[tot].next=head[u];head[u]=tot++;
}
void init(){tot=0;for(int i=0;i<=n;i++){head[i]=-1;vis[i]=0;dis[i]=mnf;}while(!q.empty()) q.pop();
}
void spfa(){dis[s]=0;vis[s]=1;q.push(s);while(!q.empty()){int u=q.front();q.pop();vis[u]=0;for(int i=head[u];~i;i=edge[i].next){if(dis[edge[i].to]>dis[u]+edge[i].w){dis[edge[i].to]=dis[u]+edge[i].w;if(!vis[edge[i].to]){vis[edge[i].to]=1;q.push(edge[i].to);}}}}
}
int main(){ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);cin>>n>>m>>s>>t;init();for(int i=1;i<=m;i++){cin>>u>>v>>w;add(u,v,w);add(v,u,w);}spfa();if(dis[t]==mnf) cout<<-1<<'\n';else cout<

2.信使

1128. 信使 - AcWing题库

题意:

这个就是跑一遍最短路,预处理一下dis数组,然后去看dis最大值就行

Code:

#include 
using namespace std;
const int mxn=2e2+10,mxe=2e2+10,mnf=0x3f3f3f3f,inf=0xc0c0c0c0;
struct ty{int to,next,w;
}edge[mxe<<1];
queue q;
int n,m,x,y,w,tot=0;
int head[mxn],dis[mxn],vis[mxn];
void add(int u,int v,int w){edge[tot].w=w;edge[tot].to=v;edge[tot].next=head[u];head[u]=tot++;
}
void init(){tot=0;for(int i=0;i<=n;i++){vis[i]=0;head[i]=-1;dis[i]=mnf;}while(!q.empty()) q.pop();
}
void spfa(){dis[1]=0;vis[1]=1;q.push(1);while(!q.empty()){int u=q.front();q.pop();vis[u]=0;for(int i=head[u];~i;i=edge[i].next){if(dis[edge[i].to]>dis[u]+edge[i].w){dis[edge[i].to]=dis[u]+edge[i].w;if(!vis[edge[i].to]){q.push(edge[i].to);vis[edge[i].to]=1;}}}}
}
int main(){ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);cin>>n>>m;init();for(int i=1;i<=m;i++){cin>>x>>y>>w;add(x,y,w);add(y,x,w);}spfa();int ans=inf;for(int i=1;i<=n;i++){if(dis[i]==mnf){cout<<-1<<'\n';return 0;}ans=max(ans,dis[i]);}cout<

 3.香甜的黄油

1127. 香甜的黄油 - AcWing题库

枚举就行,枚举奶油放在哪个点上,每个点都去跑一遍最短路,然后去看奶油放在哪个点上牛牛到奶油的距离之和最小

Code:

#include 
using namespace std;
const int mxn=2e3+10,mxe=2e3+10,mnf=0x3f3f3f3f;
struct ty{int to,next,w;
}edge[mxe<<1];
struct ty2{int x,dis;bool operator< (const ty2 &a) const{return a.dis mp;
priority_queue q;
int N,n,m,x,y,w,tot=0;
int head[mxn],dis[mxn],vis[mxn];
void add(int u,int v,int w){edge[tot].w=w;edge[tot].to=v;edge[tot].next=head[u];head[u]=tot++;
}
void init(){tot=0;mp.clear();for(int i=0;i<=n;i++){head[i]=-1;dis[i]=mnf;vis[i]=0;}while(!q.empty()) q.pop();
}
void init2(){for(int i=0;i<=n;i++){vis[i]=0;dis[i]=mnf;}while(!q.empty()) q.pop();
}
int dij(int s){init2();dis[s]=0;ty2 u;u.dis=dis[s],u.x=s;q.push(u);while(!q.empty()){ty2 u=q.top();q.pop();if(vis[u.x]) continue;vis[u.x]=1;for(int i=head[u.x];~i;i=edge[i].next){if(vis[edge[i].to]) continue;if(dis[edge[i].to]>dis[u.x]+edge[i].w){dis[edge[i].to]=dis[u.x]+edge[i].w;ty2 tmp;tmp.dis=dis[edge[i].to];tmp.x=edge[i].to;q.push(tmp);}}}int res=0;for(int i=1;i<=n;i++){if(mp[i]){if(dis[i]==mnf) return mnf;res+=dis[i]*mp[i];}}return res;
}
int main(){ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);cin>>N>>n>>m;init();for(int i=1;i<=N;i++) cin>>x,mp[x]++;for(int i=1;i<=m;i++){cin>>x>>y>>w;add(x,y,w);add(y,x,w);}int ans=mnf;for(int i=1;i<=n;i++){ans=min(ans,dij(i));}cout<

 4.最小花费

1126. 最小花费 - AcWing题库

题意:

思路:

转化为A*w1*w2*....*wn=B,即求w1*w2*....*wn最小值,其中wi为扣除的百分比

那么我们可以建图:

结点表示人

边权表示扣除的百分比

建完图后,可以发现我们要求的就是边权最小积

那么我们怎么从最小和转换到最小积:取对数就好了

lg(w1*w2*....*wn)=lgw1+lgw2+....+lgwn

因为lg函数始终是单调递增的,因此要求w1*w2*....*wn的最小值,就求lg(w1*w2*....*wn)的最小值

即求lgw1+lgw2+....+lgwn的最小值

即求lgwi的最小值

因此我们可以按照wi的大小去跑一遍最短路,然后跑的时候dist的值维护边权积就可以了

Code:

#include 
using namespace std;
const int mxn=2e3+10,mxe=1e5+10,mnf=0x3f3f3f3f;
struct ty{int to,next;double w;
}edge[mxe<<1];
queue q;
int n,m,x,y,w,tot=0,s,t;
int head[mxn],vis[mxn];
double dis[mxn];
void add(int u,int v,double w){edge[tot].w=w;edge[tot].to=v;edge[tot].next=head[u];head[u]=tot++;
}
void init(){tot=0;for(int i=0;i<=n;i++){head[i]=-1;vis[i]=0;}while(!q.empty()) q.pop();
}
double spfa(int u,int v){dis[u]=1;q.push(u);while(!q.empty()){int u=q.front();q.pop();vis[u]=0;for(int i=head[u];~i;i=edge[i].next){if(dis[edge[i].to]

5.最优乘车

920. 最优乘车 - AcWing题库

题意:

 思路:

换乘次数=坐车次数-1

因此我们只需要维护坐车次数就行

首先先建图:

结点就是公交车站

边权意义就设成坐车次数

那么在同一线路上的车站之间的坐车次数都为1,因此同一线路上的车站之间都连一条边权为1的边

不同线路的车站之间的坐车次数就可以根据跑最短路来求了

时间复杂度为O(M*(N-1)*N/2)

Code:

#include 
using namespace std;
const int mxn=5e2+10,mxe=5e2+10,mnf=0x3f3f3f3f;
struct ty{int to,next,w;
}edge[mxe<<1];
queue q;
string s;
int m,n,len=0,p,tot=0;
int a[mxn],head[mxn],dis[mxn],vis[mxn];
void add(int u,int v,int w){edge[tot].w=w;edge[tot].to=v;edge[tot].next=head[u];head[u]=tot++;
}
void init(){tot=0;len=0;s.clear();for(int i=0;i<=n;i++){head[i]=-1;dis[i]=mnf;}while(!q.empty()) q.pop();
}
void spfa(){dis[1]=0;vis[1]=1;q.push(1);while(!q.empty()){int u=q.front();q.pop();vis[u]=0;for(int i=head[u];~i;i=edge[i].next){if(dis[edge[i].to]>dis[u]+edge[i].w){dis[edge[i].to]=dis[u]+edge[i].w;if(!vis[edge[i].to]){vis[edge[i].to]=1;q.push(edge[i].to);}}}}
}
int main(){ios::sync_with_stdio(0), cin.tie(0), cout.tie(0);cin>>m>>n;init();getline(cin,s);for(int i=1;i<=m;i++){len=0;getline(cin,s);stringstream ssin(s);while(ssin>>p) a[++len]=p; for(int i=1;i<=len;i++){for(int j=i+1;j<=len;j++){add(a[i],a[j],1);add(a[j],a[i],1);}}}spfa();if(dis[n]==mnf) cout<<"NO"<<'\n';else cout<

总结:

建图的过程分成以下阶段:

1.确定结点的意义

2.确定边权的意义

结点一般都很显然,但是边权的意义我们一般把它设成对答案(或需要维护的东西)的贡献

相关内容

热门资讯

喜欢穿一身黑的男生性格(喜欢穿... 今天百科达人给各位分享喜欢穿一身黑的男生性格的知识,其中也会对喜欢穿一身黑衣服的男人人好相处吗进行解...
发春是什么意思(思春和发春是什... 本篇文章极速百科给大家谈谈发春是什么意思,以及思春和发春是什么意思对应的知识点,希望对各位有所帮助,...
网络用语zl是什么意思(zl是... 今天给各位分享网络用语zl是什么意思的知识,其中也会对zl是啥意思是什么网络用语进行解释,如果能碰巧...
为什么酷狗音乐自己唱的歌不能下... 本篇文章极速百科小编给大家谈谈为什么酷狗音乐自己唱的歌不能下载到本地?,以及为什么酷狗下载的歌曲不是...
华为下载未安装的文件去哪找(华... 今天百科达人给各位分享华为下载未安装的文件去哪找的知识,其中也会对华为下载未安装的文件去哪找到进行解...
怎么往应用助手里添加应用(应用... 今天百科达人给各位分享怎么往应用助手里添加应用的知识,其中也会对应用助手怎么添加微信进行解释,如果能...
家里可以做假山养金鱼吗(假山能... 今天百科达人给各位分享家里可以做假山养金鱼吗的知识,其中也会对假山能放鱼缸里吗进行解释,如果能碰巧解...
四分五裂是什么生肖什么动物(四... 本篇文章极速百科小编给大家谈谈四分五裂是什么生肖什么动物,以及四分五裂打一生肖是什么对应的知识点,希...
一帆风顺二龙腾飞三阳开泰祝福语... 本篇文章极速百科给大家谈谈一帆风顺二龙腾飞三阳开泰祝福语,以及一帆风顺二龙腾飞三阳开泰祝福语结婚对应...
美团联名卡审核成功待激活(美团... 今天百科达人给各位分享美团联名卡审核成功待激活的知识,其中也会对美团联名卡审核未通过进行解释,如果能...