单身三连之二
一道正解不可靠,暴力碾标算的题。
题目大意:
有一张无向图,求经过起点的最小环。(点数N<=1×104,边数M<=4×104,多测,无解输出-1)
题解:
先判断图的合法性。从起点开始dfs,判断能否从其他路径回到起点,若搜索失败,则一定无解。
已知图是合法的,我们可以将连接起点的边断掉,对每个起点连接的点跑一遍Dijkstra,求出两点间的最短路径,然后枚举更新,用两个不同的和起点相连的点去更新答案。
注意细节处理和赋极大值,多测要清空。
理论复杂度O(N2logM),不过由于和起点相连的点较少,复杂度远远达不到上界。如果遇到菊花图,则Dijkstra表现会非常优秀,不易被卡掉。
此题用spfa或A*也可做。spfa用法和Dijkstra相似。A*搜索时要注意不能沿已走过的边回去,剪枝就行,实际复杂度最低,不过码量较大。
Code:

1 #include<iostream>
2 #include<cstdio>
3 #include<queue>
4 #include<cstring>
5 using namespace std;
6 const int N=10010;
7 const int M=40010;
8 const int inf=99999999;
9 int t,n,m,nm=1;
10 int fi[N],in[N],d[N],de[N];
11 bool vis[N],v[N];
12 struct edge{
13 int u,v,l,ne;
14 }e[M<<1];
15 struct point{
16 int id,d;
17 friend bool operator < (const point a1,const point a2)
18 {
19 return a1.d>a2.d;
20 }
21 }p[N];
22 priority_queue<point> q;
23 void add(int x,int y,int z)
24 {
25 e[++nm].u=x;
26 e[nm].v=y;
27 e[nm].l=z;
28 e[nm].ne=fi[x];
29 fi[x]=nm;
30 }
31 int read()
32 {
33 int s=0;
34 char c=getchar();
35 while(c<'0'||c>'9') c=getchar();
36 while(c>='0'&&c<='9'){
37 s=(s<<3)+(s<<1)+c-'0';
38 c=getchar();
39 }
40 return s;
41 }
42 void clean()
43 {
44 memset(fi,0,sizeof(fi));
45 memset(in,0,sizeof(in));
46 memset(vis,false,sizeof(vis));
47 memset(v,false,sizeof(v));
48 memset(d,0,sizeof(d));
49 for(int i=1;i<=10000;i++) de[i]=inf;
50 nm=1;
51 }
52 bool dfs(int x,int p)
53 {
54 vis[x]=true;
55 for(int i=fi[x];i!=0;i=e[i].ne){
56 int y=e[i].v;
57 if(y==1&&p!=1) return true;
58 if(vis[y]) continue;
59 if(dfs(y,x)) return true;
60 }
61 return false;
62 }
63 void Dij(int now)
64 {
65 for(int i=1;i<=n;i++){
66 p[i].d=inf;
67 v[i]=false;
68 }
69 p[now].d=0;
70 q.push(p[now]);
71 while(!q.empty()){
72 point x=q.top();q.pop();
73 if(v[x.id])
74 continue;
75 v[x.id]=true;
76 for(int i=fi[x.id];i!=0;i=e[i].ne){
77 int y=e[i].v;
78 if(y==1) continue;
79 if(p[y].d>x.d+e[i].l){
80 p[y].d=x.d+e[i].l;
81 q.push(p[y]);
82 }
83 }
84 }
85 for(int i=2;i<=n;i++)
86 if(i!=now) de[i]=min(de[i],d[now]+p[i].d);
87 }
88 int main()
89 {
90 t=read();
91 while(t--)
92 {
93 clean();n=read();m=read();
94 for(int i=1;i<=m;i++){
95 int x=read(),y=read(),z=read();
96 in[x]++;in[y]++;add(x,y,z);add(y,x,z);
97 }
98 if(!dfs(1,0)){
99 printf("-1\n");
100 continue;
101 }
102 for(int i=1;i<=n;i++){
103 d[i]=inf;
104 p[i].id=i;
105 }
106 for(int i=fi[1];i!=0;i=e[i].ne){
107 int y=e[i].v;
108 d[y]=e[i].l;
109 Dij(y);
110 }
111 int ans=inf;
112 for(int i=2;i<=n;i++) ans=min(ans,d[i]+de[i]);
113 printf("%d\n",ans);
114 }
115 return 0;
116 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步