• POJ3164 Command Network(最小树形图)


    图论填个小坑。以前就一直在想,无向图有最小生成树,那么有向图是不是也有最小生成树呢,想不到还真的有,叫做最小树形图,网上的介绍有很多,感觉下面这个博客介绍的靠谱点:

    http://www.cnblogs.com/vongang/archive/2012/07/18/2596851.html

    所以下面的代码也是抄上面的模板的。里面还给出了不定根情况下的最小树形图的做法,新增一个虚拟根,连向其它所有点的费用是总费用+1,然后跑一次算法就可以了,这样可以保证虚拟根一定连出去某个顶点,而且不可能连两个,最后跑出来把多的费用减掉就可以了。感觉想法挺神奇的。

    #pragma warning(disable:4996)
    #include <iostream>
    #include <cstring>
    #include <string>
    #include <vector>
    #include <cstdio>
    #include <algorithm>
    #include <cmath>
    using namespace std;
    
    #define maxn 120
    #define maxm 12000
    
    int n, m;
    
    struct Edge{
    	int u, v;
    	double w;
    	Edge(int ui, int vi, double wi) :u(ui), v(vi), w(wi){}
    	Edge(){}
    };
    
    vector<Edge> E;
    
    double x[maxn], y[maxn];
    
    double dist(int i, int j){
    	return sqrt((x[i] - x[j])*(x[i] - x[j]) + (y[i] - y[j])*(y[i] - y[j]));
    }
    
    double in[maxn]; // minimum pre edge weight
    int pre[maxn]; // pre vertex
    int vis[maxn]; // vis array
    int id[maxn]; // mark down the id
    int nv; // nv is the number of vertex after shrinking
    
    double directed_mst(int root)
    {
    	double ret = 0; int nv = n;
    	while (1){
    		for (int i = 0; i < nv; ++i) in[i] = 1e10;
    		for (int i = 0; i < m; ++i){
    			int u = E[i].u, v = E[i].v;
    			if (E[i].w < in[v] && u != v){
    				in[v] = E[i].w;
    				pre[v] = u;
    			}
    		}
    		// found not connected means impossible
    		for (int i = 0; i < nv; ++i){
    			if (i == root) continue;
    			if (in[i]>1e9) return -1;
    		}
    		int cnt = 0;
    		memset(id, -1, sizeof(id));
    		memset(vis, -1, sizeof(vis));
    		in[root] = 0;
    
    		for (int i = 0; i < nv; ++i){
    			ret += in[i];
    			int v = i;
    
    			while (vis[v] != i&&id[v] == -1 && v != root){
    				vis[v] = i;
    				v = pre[v];
    			}
    			// v!=root means we find a circle,id[v]==-1 guarantee that it's not shrinked.
    			if (v != root&&id[v] == -1){
    				for (int u = pre[v]; u != v; u = pre[u]){
    					id[u] = cnt;
    				}
    				id[v] = cnt++;
    			}
    		}
    		if (cnt == 0) break;
    		for (int i = 0; i < nv; ++i){
    			if (id[i] == -1) id[i] = cnt++;
    		}
    		// change the cost of edge for each (u,v,w)->(u,v,w-in[v])
    		for (int i = 0; i < m; ++i){
    			int v = E[i].v;
    			E[i].u = id[E[i].u];
    			E[i].v = id[E[i].v];
    			if (E[i].u != E[i].v) E[i].w -= in[v];
    		}
    		// mark down the new root
    		root = id[root];
    		// mark down the new vertex number
    		nv = cnt;
    	}
    	return ret;
    }
    
    int main()
    {
    	while (cin >> n >> m){
    		E.clear();
    		for (int i = 0; i < n; ++i){
    			scanf("%lf%lf", x + i, y + i);
    		}
    		int ui, vi;
    		for (int i = 0; i < m; ++i){
    			scanf("%d%d", &ui, &vi);
    			--ui; --vi;
    			if (ui != vi) E.push_back(Edge(ui, vi, dist(ui,vi)));
    		}
    		m = E.size();
    		double ans = directed_mst(0);
    		if (ans < 0) puts("poor snoopy");
    		else printf("%.2f
    ", ans);
    	}
    	return 0;
    }
    
  • 相关阅读:
    ajax参考增删改查
    linux 断网 扫描基本命令
    linux 基本命令大全
    开发者用的linux系统推荐
    python DRF获取参数介绍
    python DRF操作流程
    python 异常处理函数--raise
    DRF-Rest_Framework 学习文档
    前端框架VUE
    python Django rest-framework 创建序列化工程步骤
  • 原文地址:https://www.cnblogs.com/chanme/p/3890872.html
Copyright © 2020-2023  润新知