hdu 4085 Peach Blossom Spring

Posted Schenker

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu 4085 Peach Blossom Spring相关的知识,希望对你有一定的参考价值。

Peach Blossom Spring

题意:有n个城市,m条路,[1,k]的城市有居民, [n-k+1, n]的城市有庇护所, 现在要修路, 使得每一座城市的居民都可以到达一个庇护所, 并且一个庇护所只能容纳一个城市的居民, 现在求所有城市的居民都能到达庇护所的最小花费。

题解:斯坦纳树跑出花费。 d[i][state] = cost, i代表的是第i个城市, state代表的是联通的状态, val代表的是花费。

先跑出所有的d[i][state]的花费。然后由于不需要是联通图, 再最后跑出每种符合的最小花费。

技术分享图片
  1 #include<bits/stdc++.h>
  2 using namespace std;
  3 #define Fopen freopen("_in.txt","r",stdin); freopen("_out.txt","w",stdout);
  4 #define LL long long
  5 #define ULL unsigned LL
  6 #define fi first
  7 #define se second
  8 #define pb push_back
  9 #define lson l,m,rt<<1
 10 #define rson m+1,r,rt<<1|1
 11 #define max3(a,b,c) max(a,max(b,c))
 12 #define min3(a,b,c) min(a,min(b,c))
 13 typedef pair<int,int> pll;
 14 const int inf = 0x3f3f3f3f;
 15 const LL INF = 0x3f3f3f3f3f3f3f3f;
 16 const LL mod =  (int)1e9+7;
 17 const int N = 55, M = 2005;
 18 int head[N], nt[M], to[M], ct[M], tot;
 19 int d[N][1<<10], s[N], vis[N][1<<10], dp[1<<10];
 20 int n, m, k, nn;
 21 void init(){
 22     memset(head, -1, sizeof(head));
 23     memset(s, 0, sizeof(s));
 24     tot = 0;
 25 }
 26 inline void add(int u, int v, int w){
 27     to[tot] = v;
 28     ct[tot] = w;
 29     nt[tot] = head[u];
 30     head[u] = tot++;
 31 }
 32 void input(){
 33     int u, v, c;
 34     for(int i = 1; i <= m; i++){
 35         scanf("%d%d%d", &u, &v, &c);
 36         add(u, v, c);
 37         add(v, u, c);
 38     }
 39     for(int i = 1; i <= n; i++)
 40         for(int j = 0; j < nn; j++) d[i][j] = inf;
 41     for(int i = 1; i <= k; i++){
 42         s[i] = 1<<(i-1); d[i][s[i]] = 0;
 43         s[n-i+1] = 1<<(k+i-1), d[n-i+1][s[n-i+1]] = 0;
 44     }
 45 }
 46 queue<int> q;
 47 inline bool update(int x, int y, int w){
 48     if(d[x][y] <= w) return false;
 49     d[x][y] = w;
 50     return true;
 51 }
 52 void spfa(){
 53     int t, x, y;
 54     while(!q.empty()){
 55         t = q.front();
 56         q.pop();
 57         x = t / 10000, y = t%10000;
 58         vis[x][y] = 0;
 59         for(int i = head[x]; ~i; i = nt[i]){
 60             if(update(to[i],y|s[to[i]],d[x][y]+ct[i]) && y == (y|s[to[i]]) && !vis[to[i]][y]){
 61                 vis[to[i]][y] = 1;
 62                 q.push(to[i]*10000+y);
 63             }
 64         }
 65     }
 66 }
 67 bool check(int x){
 68     int r = 0;
 69     for(int i = 0;x;i++, x>>=1)
 70         r += (x&1)*(i<k?1:-1);
 71     return r==0;
 72 }
 73 void solve(){
 74     for(int i = 0; i < nn; i++){
 75         for(int j = 1; j <= n; j++){
 76             for(int k = (i-1)&i; k; k = (k-1)&i)
 77                 d[j][i] = min(d[j][i], d[j][k|s[j]]+d[j][s[j]|(i-k)]);
 78             if(d[j][i] < inf) q.push(i+j*10000), vis[j][i] = 1;
 79         }
 80         spfa();
 81     }
 82     for(int i = 0; i < nn; i++){
 83         dp[i] = inf;
 84         for(int j = 1; j <= n; j++) dp[i] = min(dp[i], d[j][i]);
 85     }
 86     for(int i = 1; i < nn; i++){
 87         if(check(i)){
 88             for(int j = i&(i-1); j; j = (j-1)&i){
 89                 if(check(j)) dp[i] = min(dp[i], dp[j]+dp[i-j]);
 90             }
 91         }
 92     }
 93     if(dp[nn-1]>=inf) puts("No solution");
 94     else printf("%d
", dp[nn-1]);
 95 }
 96 int main(){
 97     int t, u, v, c;
 98     scanf("%d", &t);
 99     while(t--){
100         init();
101         scanf("%d%d%d", &n, &m, &k);
102         nn = 1<<(2*k);
103         input();
104         solve();
105     }
106     return 0;
107 }
View Code

 

以上是关于hdu 4085 Peach Blossom Spring的主要内容,如果未能解决你的问题,请参考以下文章

HDU 4085 Peach Blossom Spring 斯坦纳树 状态压缩DP+SPFA

HDU 4081 Peach Blossom Spring (最小生成树+dfs)

HDU 4085 斯坦纳树+DP

TOJ 4085 Drainage Ditches(最大流)

BZOJ 4085 丧心病狂的毒瘤题目

Magnolia Blossom : 两个页面共享同一个区域