【HDOJ】3311 Dig The Wells
Steiner Tree。概念就不讲了,引入0号结点。[1, n+m]到0连一条边,权重表示挖井的费用。这样建图spfa求MST即满足所求解。
1 /* 3311 */ 2 #include <iostream> 3 #include <string> 4 #include <map> 5 #include <queue> 6 #include <set> 7 #include <stack> 8 #include <vector> 9 #include <deque> 10 #include <algorithm> 11 #include <cstdio> 12 #include <cmath> 13 #include <ctime> 14 #include <cstring> 15 #include <climits> 16 #include <cctype> 17 #include <cassert> 18 #include <functional> 19 #include <iterator> 20 #include <iomanip> 21 using namespace std; 22 //#pragma comment(linker,"/STACK:102400000,1024000") 23 24 #define sti set<int> 25 #define stpii set<pair<int, int> > 26 #define mpii map<int,int> 27 #define vi vector<int> 28 #define pii pair<int,int> 29 #define vpii vector<pair<int,int> > 30 #define rep(i, a, n) for (int i=a;i<n;++i) 31 #define per(i, a, n) for (int i=n-1;i>=a;--i) 32 #define clr clear 33 #define pb push_back 34 #define mp make_pair 35 #define fir first 36 #define sec second 37 #define all(x) (x).begin(),(x).end() 38 #define SZ(x) ((int)(x).size()) 39 #define lson l, mid, rt<<1 40 #define rson mid+1, r, rt<<1|1 41 42 typedef struct { 43 int v, w, nxt; 44 } edge_t; 45 46 const int INF = 0x3f3f3f3f; 47 const int maxst = 65; 48 const int maxn = 1010; 49 const int maxe = 13005; 50 edge_t E[maxe]; 51 int head[maxn], l; 52 int dp[maxn][maxst]; 53 bool visit[maxn][maxst]; 54 int n, m; 55 queue<pii> Q; 56 57 void init() { 58 l = 0; 59 memset(head, -1, sizeof(head)); 60 memset(dp, INF, sizeof(dp)); 61 memset(visit, false, sizeof(visit)); 62 } 63 64 void addEdge(int u, int v, int w) { 65 E[l].v = v; 66 E[l].w = w; 67 E[l].nxt = head[u]; 68 head[u] = l++; 69 70 E[l].v = u; 71 E[l].w = w; 72 E[l].nxt = head[v]; 73 head[v] = l++; 74 } 75 76 void spfa() { 77 int u, v, st, nst; 78 79 while (!Q.empty()) { 80 u = Q.front().fir; 81 st = Q.front().sec; 82 visit[u][st] = false; 83 Q.pop(); 84 for (int i=head[u]; i!=-1; i=E[i].nxt) { 85 v = E[i].v; 86 nst = st; 87 if (v <= n) 88 nst |= (1<<v); 89 if (dp[u][st]+E[i].w < dp[v][nst]) { 90 dp[v][nst] = dp[u][st]+E[i].w; 91 if (nst==st && !visit[v][nst]) { 92 visit[v][nst] = true; 93 Q.push(mp(v, nst)); 94 } 95 } 96 } 97 } 98 } 99 100 void solve() { 101 int mst = 1<<(n+1); 102 int nn = n + m + 1; 103 int kk, kk_; 104 105 rep(i, 0, n+1) 106 dp[i][1<<i] = 0; 107 108 rep(i, 0, mst) { 109 rep(j, 0, nn) { 110 rep(k, 1, i) { 111 if ((k|i) == i) { 112 kk = k; 113 kk_ = i - k; 114 if (j <= n) { 115 kk |= (1<<j); 116 kk_ |= (1<<j); 117 } 118 dp[j][i] = min(dp[j][i], dp[j][kk]+dp[j][kk_]); 119 } 120 } 121 if (dp[j][i] != INF) { 122 Q.push(mp(j, i)); 123 visit[j][i] = true; 124 } 125 } 126 spfa(); 127 } 128 129 int ans = INF; 130 rep(j, 0, nn) 131 ans = min(ans, dp[j][mst-1]); 132 printf("%d\n", ans); 133 } 134 135 int main() { 136 ios::sync_with_stdio(false); 137 #ifndef ONLINE_JUDGE 138 freopen("data.in", "r", stdin); 139 freopen("data.out", "w", stdout); 140 #endif 141 142 int p; 143 int u, v, w; 144 145 while (scanf("%d %d %d",&n,&m,&p)!=EOF) { 146 init(); 147 rep(i, 1, n+m+1) { 148 scanf("%d", &w); 149 addEdge(0, i, w); 150 } 151 rep(i, 0, p) { 152 scanf("%d %d %d", &u, &v, &w); 153 addEdge(u, v, w); 154 } 155 solve(); 156 } 157 158 #ifndef ONLINE_JUDGE 159 printf("time = %d.\n", (int)clock()); 160 #endif 161 162 return 0; 163 }