zoukankan      html  css  js  c++  java
  • 2019ICPC邀请赛南昌A Attack 斯坦纳树

    先对8个点整体做斯坦纳树,再求出每个状态的最小代价。再看每个状态是否属于独立的,即包含的点都是成对的,我们去更新这些独立的状态即可。

      1 #include <cstdio>
      2 #include <cstring>
      3 #include <string>
      4 #include <map>
      5 #include <queue>
      6 #include <iostream>
      7 using namespace std;
      8 const int MAXN = 40,MAXM = 2100;
      9 queue <int> que;
     10 string s1,s2;
     11 map <string,int> mp;
     12 bool inq[MAXN];
     13 int head[MAXN],dis[MAXN][1 << 8],ans[1 << 8],spe[1 << 8],to[MAXM],nxt[MAXM],val[MAXM];
     14 int cnt,n,m,s,t,inf;
     15 void add(int x,int y,int v)
     16 {
     17     nxt[++cnt] = head[x];
     18     to[cnt] = y;
     19     val[cnt] = v;
     20     head[x] = cnt;
     21 }
     22 void SPFA(int o)
     23 {
     24     while(!que.empty())
     25     {
     26         int t = que.front();
     27         que.pop();
     28         inq[t] = false;
     29         for(int i = head[t];i;i = nxt[i])
     30         {
     31             if(dis[to[i]][o] > dis[t][o] + val[i])
     32             {
     33                 dis[to[i]][o] = dis[t][o] + val[i];
     34                 if(!inq[to[i]])
     35                 {
     36                     inq[to[i]] = true;
     37                     que.push(to[i]);
     38                 }
     39             }
     40         }
     41     }
     42 }
     43 void steiner_tree()
     44 {
     45     for (int i = 0;i < (1 << 8);i++)
     46     {
     47         for (int j = 1;j <= n;j++)
     48         {
     49             for (int k = i;k;k = (k - 1) & i)
     50                 dis[j][i] = min(dis[j][i],dis[j][k] + dis[j][i - k]);
     51             if (dis[j][i] != inf)
     52             {
     53                 que.push(j);
     54                 inq[j] = true;
     55             }
     56         }
     57         SPFA(i);
     58     }
     59 }
     60 bool check(int o)
     61 {
     62     for (int i = 0;i <= 7;i += 2)
     63         if (((o >> i) & 1) ^ ((o >> (i + 1)) & 1))
     64             return false;
     65     return true;
     66 }
     67 int main()
     68 {
     69     while (scanf("%d%d",&n,&m) > 0)
     70     {
     71         cnt = 0;
     72         memset(head,0,sizeof(head));
     73         memset(nxt,0,sizeof(nxt)); 
     74         memset(dis,0x1f,sizeof(dis));
     75         memset(ans,0x1f,sizeof(ans)); 
     76         inf = ans[0];
     77         int tv;
     78         string s1,s2;
     79         for (int i = 1;i <= n;i++)
     80         {
     81             cin >> s1;
     82             mp[s1] = i;
     83         }
     84         for (int i = 1;i <= m;i++)
     85         {
     86             cin >> s1 >> s2;
     87             scanf("%d",&tv);
     88             add(mp[s1],mp[s2],tv);
     89             add(mp[s2],mp[s1],tv);
     90         }
     91         for (int i = 1;i <= 8;i++)
     92         {
     93             cin >> s1;
     94             dis[mp[s1]][1 << (i - 1)] = 0;
     95         }
     96         steiner_tree();
     97         for (int i = 0;i < (1 << 8);i++)
     98         {
     99             spe[i] = check(i);
    100             for (int j = 1;j <= n;j++)
    101                 ans[i] = min(ans[i],dis[j][i]); 
    102         }
    103         for (int i = 0;i < (1 << 8);i++)
    104             if (spe[i])
    105                 for (int j = i;j;j = (j - 1) & i)
    106                     if (spe[j] && spe[i - j])
    107                         ans[i] = min(ans[i],ans[j] + ans[i - j]);
    108         printf("%d
    ",ans[(1 << 8) - 1]);
    109     }
    110     return 0;
    111 }
  • 相关阅读:
    【面积并】 Atlantis
    【动态前k大 贪心】 Gone Fishing
    【复杂枚举】 library
    【双端队列bfs 网格图建图】拯救大兵瑞恩
    【奇偶传递关系 边带权】 奇偶游戏
    【权值并查集】 supermarket
    CF w4d3 A. Pythagorean Theorem II
    CF w4d2 C. Purification
    CF w4d2 B. Road Construction
    CF w4d2 A. Cakeminator
  • 原文地址:https://www.cnblogs.com/iat14/p/12441165.html
Copyright © 2011-2022 走看看