标签:while 挑战 任务 博客 print class span 返回 部分
#include <stdio.h> #include<queue> #include<vector> #include <memory.h> using std::queue; using std::vector; /* *dp: *dp[i][st] 包含第i个点,且至少和state为1的关键点相连的最小花费 *转移 *dp[i][st]=Min{dp[i][st],dp[i][st-sub]+dp[i][sub]} 分解为两个 *dp[i][st]=Min{dp[i][st],dp[j][st]+w(i,j)} i和j有边,关键点外面的部分spfa一下 */ #define INF 0x3f3f3f3f #define maxn 55 int g[maxn][maxn]; int dp[maxn][1 << 12]; queue<int> help; int N,K; int vis[maxn]; struct DeliveryCost { int u; int v; int cost; }; void spfa(int cs){ while(!help.empty()) { int id = help.front();help.pop(); vis[id] = 0; for(int i=1;i<=N;++i){ if (id == i || g[id][i] == INF)continue; if(dp[i][cs]>dp[id][cs]+g[id][i]){ dp[i][cs] = dp[id][cs] + g[id][i]; if(!vis[i]){ vis[i] = 1; help.push(i); } } } } } int solve(int n, vector<DeliveryCost> cost_e, vector<int> employees, vector<int> cost_b) { /*********begin*********/ memset(g, 0x3f, sizeof g); memset(dp, 0x3f, sizeof dp); //建图 //员工到员工 int sz = cost_e.size(); int tu, tv, tc; for(int i=0;i<sz;i++) { tu = cost_e[i].u; tv = cost_e[i].v; tc = cost_e[i].cost; g[tu][tv] = tc; g[tv][tu] = tc; } //老板到特殊员工 K = cost_b.size(); for(int i=0;i<K;i++) { g[n + 1][employees[i]] = cost_b[i]; g[employees[i]][n+1] = cost_b[i]; dp[employees[i]][1 << i] = 0; } dp[n + 1][1 << K] = 0; K++; N=n+1; int limit = (1 << K) - 1; //第一层转移 for(int sta=0;sta<=limit;sta++) {//遍历state for(int i=1;i<=N;i++) { for(int s=sta;s;s=(s-1)&sta) //遍历substate if(dp[i][s]+dp[i][sta-s]<dp[i][sta]) dp[i][sta] = dp[i][s] + dp[i][sta - s]; if (dp[i][sta] < INF) {//i-sta被松弛,放入队列 help.push(i); vis[i] = 1; } } //第二层转移 spfa(sta); } //N是特殊点中的一个 return dp[N][limit]; /*********end*********/ } int main(){ //测试一下样例 int n = 3; vector<DeliveryCost>cost_e{ { 1, 2, 2 },{ 1, 3, 2 },{ 2, 3, 2 } }; vector<int> employees{ 1,2 }; vector<int> cost_b{ 1,1000 }; printf("%d",solve(n, cost_e, employees, cost_b)); }
绿色计算大赛决赛 第二阶段 消息传递(斯坦纳树 状压dp+spfa)
标签:while 挑战 任务 博客 print class span 返回 部分
原文地址:https://www.cnblogs.com/tobyw/p/9955470.html