zoukankan      html  css  js  c++  java
  • 【POJ1734】Sightseeing trip

    题目链接:https://www.acwing.com/problem/content/346/

    题目大意:确定无向带权图上至少包含 3 个节点的最小环

    solution

    一道无向图上的最小环问题 , 考虑 (Floyd) , 设 (i)(j) 间的道路长为 (f[i][j]) , 最短路径长 (g[i][j]) , 若每次 (Floyd) 最外层 遍历到 (k) 时 , (g[i][j]) 决定了 (i)(j) 间经过节点编号不超过 (k) 的最短路径 , 不妨以 (k) 为环上的节点 , 枚举 (i)(j) , 即是枚举 (k) 在环上的相邻节点 , 那么这个环的最小长度为(f[i][k] + f[k][j] + g[i][j]) , 这样就可以找出环上节点编号不超过 (k) 的最小环 , 由对称性 , 最终可以遍历到每一个最小环

    拓展 : 对于有向图上的最小环 , 可以依次枚举起点 (s) , 再在 (dijstra)(s) 向外拓展后 , 把 (shortestpath[s]) 设为极大值 , 最终的 (shortestpath[s]) 即为从 (s) 开始的最小环的长度 , 笔者在这不多加赘述

    时间复杂度 : (O(n^3))

    code

    #include<bits/stdc++.h>
    using namespace std;
    template <typename T> inline void read(T &FF) {
    	int RR = 1; FF = 0; char CH = getchar();
    	for(; !isdigit(CH); CH = getchar()) if(CH == '-') RR = -RR;
    	for(; isdigit(CH); CH = getchar()) FF = FF * 10 + CH - 48;
    	FF *= RR;
    }
    inline void file(string str) {
    	freopen((str + ".in").c_str(), "r", stdin);
    	freopen((str + ".out").c_str(), "w", stdout);
    }
    const int N = 105;
    int g[N][N], ans = INT_MAX, f[N][N];
    int pos[N][N], n, m;
    queue<int> path;
    void get_path(int xi, int yi) {
    	if(pos[xi][yi] == 0) return;
    	get_path(xi, pos[xi][yi]);
    	path.push(pos[xi][yi]);
    	get_path(pos[xi][yi], yi);
    }
    int main() {
    	//file("");
    	int u, v, w;
    	read(n), read(m);
    	memset(g, 0x3f, sizeof(g));
    	memset(f, 0x3f, sizeof(f));
    	for(int i = 1; i <= n; i++) f[i][i] = g[i][i] = 0; 
    	for(int i = 1; i <= m; i++) {
    		read(u), read(v), read(w);
    		g[u][v] = g[v][u] = min(g[u][v], w);
    		f[u][v] = f[v][u] = g[u][v];
    	}
    	ans = f[0][0];
    	for(int k = 1; k <= n; k++) {
    		for(int i = 1; i < k; i++)
    			for(int j = i + 1; j < k; j++)
    				if((long long)g[i][j] + f[i][k] + f[k][j] < ans) {
    					ans = g[i][j] + f[i][k] + f[k][j];
    					while(!path.empty()) path.pop();
    					path.push(i);
    					get_path(i, j);
    					path.push(j); path.push(k);
    				}
    		for(int i = 1; i <= n; i++)
    			for(int j = 1; j <= n; j++)
    				if(g[i][k] + g[k][j] < g[i][j]) {
    					g[i][j] = g[i][k] + g[k][j];
    					pos[i][j] = k;
    				}
    	}
    	if(path.empty()) {
    		puts("No solution.");
    		return 0;
    	}
    	while(!path.empty()) cout << path.front() << " ", path.pop();
    	cout << endl;
    	return 0;
    }
    
    
    
    
  • 相关阅读:
    Java 递归、尾递归、非递归、栈 处理 三角数问题
    vmware虚拟机迁移导致的eth0消失问题
    c语言输入输出
    改动虚拟机镜像的rootpassword
    面试题之变态跳台阶
    努力是种病:放慢节奏,才能快速奔跑(转)
    做技术到底可以做到哪种地步-技术为什么越走越窄 (转)
    wpf 客户端【JDAgent桌面助手】开发详解(三) 瀑布流效果实现与UI虚拟化优化大数据显示
    我为什么写博客(转)
    入行必读:互联网行业薪酬等级!看看你值多少钱?(转)
  • 原文地址:https://www.cnblogs.com/magicduck/p/12241605.html
Copyright © 2011-2022 走看看