#include <iostream> #include <cstring> #include <algorithm> using namespace std; const int INF = 0x3f3f3f3f; const int N = 3010; typedef struct Node{ int number; int cost; int dis; }node; int _map[N][N],old_map[N][N];//邻接矩阵 node __map[N][N]; int n,m,cnt,top,flag; int du[N],id[N],__stack[N]; //id数组是统计奇度顶点,弗洛莱算法需要用到栈,top代表的是栈大小,flag用来结束递归 bool point_connect[N]; //标记需要连接的点 int minn ,num_edge;//num_edge统计的是奇数边的数量 int temp_edge[N],min_edge[N];//temp_edge数组临时保存匹配的奇数组合边,min_edge数组保存最小的奇数组合边 struct Edge{ int from,to,dis; }total_edge[N],odd_edge[N];//odd_edge数组代表的是奇度顶点的边 void Floyd(){ for(int k=1;k<=n;++k) for(int i=1;i<=n;++i) for(int j=1;j<=n;++j){ // _map[i][j] = min(_map[i][j],_map[i][k]+_map[k][j]); __map[i][j].dis = min(__map[i][j].dis,__map[i][k].cost+__map[k][j].cost); } } void dfs_edge(int sum,int step,int need_num){ if(step == need_num){ if(sum<minn){ for(int i=0;i<step;++i){ min_edge[i] = temp_edge[i]; } minn = sum; } } for(int i=1;i<=num_edge;++i){ int a= odd_edge[i].from; int b = odd_edge[i].to; int w = odd_edge[i].dis; if(point_connect[a]==1 && point_connect[b]==1){ point_connect[a] = point_connect[b] = 0; temp_edge[step] = i; dfs_edge(sum+w,step+1,need_num); point_connect[a] = point_connect[b] = 1; } } } void dijkstra(int st,int ed){ int dist[N]; bool used[N]; int pre[N]; memset(dist,0x3f,sizeof dist); memset(used,false,sizeof used); memset(pre,0,sizeof pre); dist[st] = 0; for(int i=0;i<n-1;++i){ int t = -1; for(int j=1;j<=n;++j){ if(!used[j] && (t==-1 || dist[j]>dist[t])) t= j; } for(int j=1;j<=n;++j){ if(dist[j]>dist[t]+old_map[t][j]){ pre[j] = t; dist[j] = dist[t] + __map[t][j].dis; } } } int backup = ed; while(backup!=st){ int pre_node = pre[backup]; __map[pre_node][backup].number++; __map[backup][pre_node].number++; backup = pre_node; } } void extend_edge(int add_edge){ num_edge = 0; for(int i=1;i<=n;++i) { if(du[i] & 1){ for(int j=i+1;j<=n;++j){ if(du[j] & 1){ point_connect[i] = point_connect[j] =1; num_edge++; odd_edge[num_edge].from = i; odd_edge[num_edge].to = j; odd_edge[num_edge].dis = _map[i][j]; } } } } minn = INF; dfs_edge(0,0,add_edge); for(int i=0;i<add_edge;++i){ int k = min_edge[i]; int a = odd_edge[k].from; int b = odd_edge[k].to; int w = odd_edge[k].dis; dijkstra(a,b); point_connect[a] =point_connect[b] = 0; } } void Fleury(int st){ int i; for(int i=1;i<=n;++i){ if(__map[st][i].number>0){ __map[st][i].number--; __map[i][st].number--; __stack[top++] = i; if(top==(m+1)){ flag = true; return ; } Fleury(i); if(flag) return ; __map[st][i].number++; __map[i][st].number++; top--; } } } int main() { cin>>n>>m; for(int i=1;i<=n;++i) for(int j=1;j<=n;++j) if(i==j) _map[i][j] = 0; else _map[i][j] = INF; for(int i=1;i<=m;++i){ int from, to ,weight; cin>>from>>to>>weight; total_edge[i] = {from,to,weight}; du[from]++,du[to]++; // _map[from][to] = weight; // old_map[from][to] = weight; __map[from][to].number++; __map[to][from].number++; __map[from][to].cost = weight; __map[to][from].cost = weight; } Floyd(); for(int i=1;i<=n;++i) if(du[i] & 1) cnt++; if(cnt==1 || cnt>2) { puts("不是欧拉回路"); return 0; } if(cnt==2){ extend_edge(cnt/2); } m+=cnt/2; int first_id = 1; if(cnt==2){ for(int i=1;i<=n;++i) { if(du[i] & 1){ first_id = i; break; } } } __stack[top++] = first_id; Fleury(first_id); char vt_point; int total_res = 0; for(int i=1;i<=m;++i){ total_res+=__map[__stack[i-1]][__stack[i]].cost; } printf("%d\n",total_res); for(int i=0;i<=m;++i){ vt_point = __stack[i]+'A'-1; printf("%c",vt_point); if(i<m){ printf("->"); } } puts(""); return 0; }
用到了最短路算法和弗洛莱算法,用结构体代替邻接矩阵
中国邮路问题
最新推荐文章于 2022-11-16 19:21:58 发布