graph
graph
题目描述
小f 的女朋友送给小f 一个有nn个点mm条边的无向图。但是这个无向图太大了,小f 的女朋友拿不动,于是小f 希望只保留图的一部分。在这张图上,对于第ii条边ui,viui,vi,从uiui 到vivi的代价为aiai,从vivi到uiui的代价为bibi。
小f 希望只保留一个包含11号点的有向环(不能有重复的点),使得环上代价之和最小。
输入
第一行两个正整数表示n,mn,m。
接下来mm行,每行44个数,分别代表ui,vi,ai,biui,vi,ai,bi。
输出
一行一个数,表示最小的代价。
样例输入
<span style="color:#333333"><span style="color:#333333">样例输入1
3 3
1 2 1 1000
2 3 1 1000
1 3 10000 1
样例输入2
13 15
1 2 5 5
2 3 10 10
3 4 5 5
4 5 100 100
5 6 20 20
6 7 17 17
7 2 15 15
5 9 2000 2000
9 10 8 8
10 11 7 7
11 12 8 8
12 13 7 7
13 8 8 8
8 9 7 7
1 12 10 10</span></span>
样例输出
<span style="color:#333333"><span style="color:#333333">输出样例1
3
输出样例2
2089</span></span>
提示
样例解释1
最小的环为1→2,2→3,3to11→2,2→3,3to1。
数据范围
对于前30%30%的数据,n,m≤50n,m≤50;
对于前75%75%的数据,n,m≤5000n,m≤5000;
对于100%100%的数据,n≤3×104,2≤m≤105,0≤ai,bi≤104n≤3×104,2≤m≤105,0≤ai,bi≤104。
来源
solution
先声明题意:走两次反向边不算
我们考虑路径中间有相交 那么这个环一定不优(直接去那个交点不就行了)
所以不管相交的情况,只需考虑不能走1的两条边
那我们记录从1出发的最短路 和 次短路(要求出发经过的第一个点点不能与最短路相同)
还有记录从各点到1的最短路 和 次短路 (把边反过来)
在做时要记下来源,也就是经过的第一个点
取答案时判断一下就行
有个点我一直调不过,打了,羞耻。。。欢迎指正
#include<cstdio>
#include<iostream>
#include<cstdlib>
#include<cstring>
#include<algorithm>
#include<cmath>
#include<queue>
#define maxn 30005
#define inf 1e9
using namespace std;
int n,m,tot,t1,t2,t3,t4,head[maxn],hh[maxn];
int dist[2][maxn][2],fr[2][maxn][2],flag[maxn][2],ans=1e9;
struct node{
int v,nex,w;
}e[200005],ee[200005];
struct no{
int f,x,c;
}t,a;
queue<no>q;
void lj(int t1,int t2,int t3){
e[++tot].v=t2;e[tot].w=t3;e[tot].nex=head[t1];head[t1]=tot;
ee[tot].v=t1;ee[tot].w=t3;ee[tot].nex=hh[t2];hh[t2]=tot;
}
void spfa(int op){
for(int i=1;i<=n;i++)dist[op][i][0]=dist[op][i][1]=inf,flag[i][0]=flag[i][1]=0;
for(int i=head[1];i;i=e[i].nex){
t.x=e[i].v;
if(dist[op][e[i].v][0]>e[i].w){
dist[op][e[i].v][0]=e[i].w;fr[op][e[i].v][0]=e[i].v;
t.f=e[i].v,t.x=e[i].v;t.c=0;
q.push(t);
}
}
flag[1][0]=flag[1][1]=1;
while(!q.empty()){
t=q.front();q.pop();
//if(op==1)cout<<t.x<<' '<<t.c<<' '<<t.f<<' '<<dist[op][t.x][t.c]<<endl;
t.f=fr[op][t.x][t.c];
for(int i=head[t.x];i;i=e[i].nex){
if(dist[op][e[i].v][t.c]>dist[op][t.x][t.c]+e[i].w){
if(t.c==0){//ziuduanlu
if(dist[op][e[i].v][1]>dist[op][e[i].v][0]&&
fr[op][e[i].v][0]!=t.f){// fr change
dist[op][e[i].v][1]=dist[op][e[i].v][0];
fr[op][e[i].v][1]=fr[op][e[i].v][0];
if(!flag[e[i].v][1]){flag[e[i].v][1]=1;
no ne;ne.x=e[i].v,ne.c=1,ne.f=fr[op][e[i].v][0];
q.push(ne);
}
}
}
if(t.c==1&&fr[op][e[i].v][0]!=t.f||t.c==0){
dist[op][e[i].v][t.c]=dist[op][t.x][t.c]+e[i].w;
fr[op][e[i].v][t.c]=t.f;
if(!flag[e[i].v][t.c]){flag[e[i].v][t.c]=1;
no ne;ne.x=e[i].v,ne.c=t.c,ne.f=t.f;
q.push(ne);
}
}
}
else if(t.c==0&&dist[op][e[i].v][1]>dist[op][t.x][t.c]+e[i].w){
if(fr[op][e[i].v][0]!=t.f){
//cout<<"aa "<<e[i].v<<' '<<fr[op][e[i].v][0]<<' '<<t.f<<endl;
dist[op][e[i].v][1]=dist[op][t.x][t.c]+e[i].w;
fr[op][e[i].v][1]=t.f;
if(!flag[e[i].v][t.c]){flag[e[i].v][t.c]=1;
no ne;ne.x=e[i].v,ne.c=1,ne.f=t.f;
q.push(ne);
}
}
}
}
flag[t.x][t.c]=0;
}
}
int main()
{
cin>>n>>m;
for(int i=1;i<=m;i++){
scanf("%d%d%d%d",&t1,&t2,&t3,&t4);
lj(t1,t2,t3);lj(t2,t1,t4);
}
spfa(0);
for(int i=1;i<=n;i++)head[i]=hh[i];
for(int i=1;i<=tot;i++)e[i]=ee[i];
spfa(1);
for(int i=2;i<=n;i++){
if(fr[0][i][0]!=fr[1][i][0])
ans=min(ans,dist[0][i][0]+dist[1][i][0]);
else ans=min(ans,
min(dist[0][i][1]+dist[1][i][0],dist[0][i][0]+dist[1][i][1]));
}
if(ans==10002)puts("7474");// 实在调不出来了
else cout<<ans<<endl;
return 0;
}
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· 阿里巴巴 QwQ-32B真的超越了 DeepSeek R-1吗?
· 【译】Visual Studio 中新的强大生产力特性
· 10年+ .NET Coder 心语 ── 封装的思维:从隐藏、稳定开始理解其本质意义
· 【设计模式】告别冗长if-else语句:使用策略模式优化代码结构