• 2019ICPC南昌邀请赛现场赛A题


    题意:

    给出一张图,求让 (4) 对点相互可以到达的最小边权值。仅要求一对之间,一对与另外一对可到达也可不到达。

    分析:

    斯坦纳树裸题,众所周知斯坦纳树仅能求出这 (4) 对点(关键点)的连通状况,如这 (4) 对点相互都连通,某点和某点连通等。然而让这 (4) 对点连通符合题目要求,但不一定是最优解(我可以让每对点直接相连),所以我们要对斯坦纳树求出的 (dp) 数组进行子集 (dp) 才能得到最优解。

    #include <bits/stdc++.h>
    using namespace std;
    
    const int N  = 50 + 5, M = 1000 + 5;
    const int inf = 0x3f3f3f3f;
    
    int n, m, w, tot, cnt, maxsta, head[N], vis[N];
    int dp[N][1 << 10], ans[1 << 11];
    string a, b;
    queue<int> q;
    map<string, int> maps;
    
    struct node {
    	int v, w, next;
    } e[M << 1];
    
    void init() {
    	tot = cnt = 0;
    	memset(dp, inf, sizeof dp);
    	memset(head, 0, sizeof head);
    	memset(vis, 0, sizeof vis);
    	while (!q.empty()) q.pop();
    	maps.clear();
    }
    
    void addedge(int u, int v, int w) {
    	e[++cnt].v = v;
    	e[cnt].w = w;
    	e[cnt].next = head[u];
    	head[u] = cnt;
    }
    
    void spfa(int sta) {
    	while (!q.empty()) {
    		int u = q.front();
    		q.pop();
    		vis[u] = 0;
    		for (int i = head[u]; i; i = e[i].next) {
    			int v = e[i].v, val = e[i].w;
    			if (dp[v][sta] > dp[u][sta] + val) {
    				dp[v][sta] = dp[u][sta] + val;
    				if (!vis[v]) q.push(v), vis[v] = 1;
    			}
    		}
    	}
    }
    
    bool check(int sta) {
    	for (int i = 0; i < 8; i += 2) {
    		if ((sta >> i & 1) ^ (sta >> (i + 1) & 1)) return false;
    	}
    	return true;
    }
    
    int main() {
    	while (cin >> n >> m) {
    		init();
    		for (int i = 1; i <= n; i++) {
    			cin >> a;
    			maps[a] = ++tot;
    		}
    		for (int i = 1; i <= m; i++) {
    			cin >> a >> b >> w;
    			addedge(maps[a], maps[b], w);
    			addedge(maps[b], maps[a], w);
    		}
    		for (int i = 0; i < 8; i++) {
    			cin >> a;
    			dp[maps[a]][1 << i] = 0;
    		}
    		maxsta = 1 << 8;
    		for (int sta = 0; sta < maxsta; sta++) {
    			while(!q.empty()) q.pop();
    			for (int i = 1; i <= n; i++) {
    				for (int s = sta; s; s = (s - 1) & sta) {
    					if(dp[i][sta] > dp[i][s] + dp[i][sta ^ s])
    						dp[i][sta] = dp[i][s] + dp[i][sta ^ s];
    				}
    				if(dp[i][sta] < inf) q.push(i), vis[i] = 1;
    			}
    			spfa(sta);
    		}
    		memset(ans, inf, sizeof ans);
    		for (int s = 0; s < maxsta; s++) {
    			if (!check(s)) continue;
    			for (int i = 1; i <= n; i++) {
    				ans[s] = min(ans[s], dp[i][s]);
    			}
    		}
    		for (int s = 0; s < maxsta; s++) {
    			if (!check(s)) continue;
    			for (int p = (s - 1) & s; p; p = (p - 1) & s)
    				ans[s] = min(ans[s], ans[p] + ans[s ^ p]);
    		}
    		cout << ans[maxsta - 1] << '
    ';
    	}
    	return 0;
    }
    
    
  • 相关阅读:
    自定义的类型放入STL的set中,需要重载自定义类中的“<”符号(转)
    C++中的explicit关键字(转)
    【小米3使用经验】小米3关闭系统自动更新(升级)
    享元模式FlyweightPattern(转)
    程序员的工作环境与效率
    Windows7远程登陆访问2003很卡的解决办法
    windows7上可以正常安装的VS2010版本
    使用Visual Studio指定命令行参数
    winform配置文件的简单使用
    Java nio epoll mina
  • 原文地址:https://www.cnblogs.com/ChaseNo1/p/11644939.html
Copyright © 2020-2023  润新知