地图游戏

题目描述

从前有一个基于一张无向图的游戏,我个人认为是比较无聊,但是出题需要,还是给你们讲讲怎么玩吧。= = 给一张地图,地图上有一些城市,城市之间可能有线路连通,我们用一个无向图来表示以简化概念,每条边有个权值,表示选择这条边需要花费的费用。给定4对顶点(可能重复),求一个权值最小的边集,使得任意一对顶点可以由选出的边集中的边相连。 按照惯例,下面给出一个例子:

输入格式

12个整数,nm,分别表示城市的个数和边的个数。

接下来n行,每行一个字符串,表示每个城市的名字。城市的名字为一个不超过20个字

符,由小写字母构成的字符串。

再接下来m行,每行给出s1,s2w,其中s1,s2为城市的名字,w为他们之间边的权值。

最后,给出4行,每行给出两个字符串,分别为要求的一对城市的名字。

输出格式

一行,输出最小的花费。

样例

样例输入:

2 1

first

second

first second 10

first first

first first

second first

first first

样例输出:

10

Sol

斯坦纳树模板题,合并一下联通关系就好啦!

Code

  1. #include <bits/stdc++.h>  
  2. using namespace std;  
  3. int las[10005],nex[10005],Arrive[10005],qz[10005],cnt,K;  
  4. int Bit[100005];  
  5. bool pd[100005];  
  6. int bel[100005],Size[100005],Temp;  
  7. int Lt[505][505];  
  8. int dis[100005][205];  
  9. int Id[100005];  
  10. int x[105],y[105];  
  11. bool vis[10005][205];  
  12. map<string,int> qwq;  
  13. void jt(int x,int y,int z)  
  14. {  
  15.     cnt++;  
  16.     nex[cnt]=las[x];  
  17.     las[x]=cnt;  
  18.     Arrive[cnt]=y;  
  19.     qz[cnt]=z;  
  20. }  
  21. queue<pair<int,int> >que;  
  22. int dp[10005];  
  23. int N,M;  
  24. void SPFA()  
  25. {  
  26.     while (!que.empty())  
  27.     {  
  28.         int u=que.front().first;  
  29.         int d=que.front().second;  
  30.         que.pop();  
  31.         vis[u][d]=false;  
  32.         for (int i=las[d];i;i=nex[i])  
  33.           {  
  34.             int v=Arrive[i];  
  35.             if (dis[u|Id[v]][v]>dis[u][d]+qz[i])  
  36.               {  
  37.                 dis[u|Id[v]][v]=dis[u][d]+qz[i];  
  38.                 if (!vis[u|Id[v]][v])  
  39.                   {  
  40.                     que.push(make_pair(u|Id[v],v));  
  41.                     vis[u|Id[v]][v]=true;  
  42.                    }  
  43.             }  
  44.           }  
  45.     }  
  46.     return;  
  47. }  
  48. int main()  
  49. {  
  50.     memset(dis,63,sizeof(dis));  
  51.     int INF=dis[0][0];  
  52.     scanf("%d%d",&N,&M);      
  53.     string s1;    
  54.     for (int i=1;i<=N;i++)  
  55.     {  
  56.         cin>>s1;  
  57.         qwq[s1]=i;  
  58.     }     
  59.     for (int i=1;i<=M;i++)  
  60.       {  
  61.         string s1,s2;  
  62.         int w;  
  63.         cin>>s1>>s2>>w;  
  64.         jt(qwq[s1],qwq[s2],w);  
  65.         jt(qwq[s2],qwq[s1],w);  
  66.       }  
  67.     
  68.     int cntt=0;  
  69.     string s2;  
  70.     for (int i=1;i<=4;i++)  
  71.       {  
  72.         int u,v;  
  73.         cin>>s1;  
  74.         u=qwq[s1];  
  75.         cin>>s2;  
  76.         v=qwq[s2];  
  77.         if (u==v)continue;  
  78.         if (bel[u]&&bel[v]){  
  79.             int upd=bel[v];if (bel[u]==bel[v])continue;  
  80.             for (int i=1;i<=Size[upd];i++)  
  81.             Lt[bel[u]][++Size[bel[u]]]=Lt[upd][i],bel[Lt[upd][i]]=bel[u];  
  82.             Size[upd]=0;  
  83.         }  
  84.         else if (bel[u]||bel[v]){  
  85.             if (bel[v])  
  86.               swap(u,v);  
  87.             bel[v]=bel[u];  
  88.             Lt[bel[u]][++Size[bel[u]]]=v;  
  89.         }  
  90.         else {  
  91.             bel[u]=bel[v]=++cntt;  
  92.             Lt[cntt][++Size[cntt]]=u;Lt[cntt][++Size[cntt]]=v;  
  93.         }  
  94.       }    
  95.     for (int i=1;i<=N;i++)  
  96.       if (bel[i])  
  97.         {  
  98.             Temp++;  
  99.             Id[i]=(1<<(Temp-1));  
  100.             dis[Id[i]][i]=0;  
  101.         }  
  102.     else dis[0][i]=0;  
  103.     int st=1<<Temp;  
  104.     for (int ST=0;ST<st;ST++)  
  105.     {  
  106.         for (int i=1;i<=N;i++)  
  107.             {  
  108.             for (int mst=(ST-1)&ST;mst;mst=(mst-1)&ST)  
  109.               dis[ST][i]=min(dis[ST][i],dis[mst|Id[i]][i]+dis[(ST-mst)|Id[i]][i]);  
  110.             if (dis[ST][i]<INF&&!vis[ST][i])  
  111.               que.push(make_pair(ST,i)),vis[ST][i]=true;  
  112.             }  
  113.         SPFA();  
  114.     }  
  115.     memset(dp,63,sizeof(dp));     
  116.     for (int i=1;i<=N;i++)  
  117.       for (int j=0;j<=st;j++)  
  118.         dp[j]=min(dis[j][i],dp[j]);  
  119.     
  120.     int Ncnt=cntt;  
  121.     cntt=0;  
  122.     for (int i=1;i<=Ncnt;i++)  
  123.       {  
  124.         if (Size[i])  
  125.           {  
  126.             cntt++;  
  127.             for (int j=1;j<=Size[i];j++)  
  128.               Bit[cntt]|=Id[Lt[i][j]];  
  129.             pd[Bit[cntt]]=true;  
  130.           }  
  131.       }  
  132.       dp[0]=0;  
  133.     for (int i=0;i<st;i++)  
  134.       for (int j=i;j;j=(j-1)&i)  
  135.           if (pd[j]&pd[i-j])  
  136.             pd[i]=true;  
  137.     for (int i=0;i<st;i++)  
  138.         if (pd[i])  
  139.          for (int j=i;j;j=(j-1)&i)  
  140.            if  (pd[j]) dp[i]=min(dp[i],dp[i-j]+dp[j]);  
  141.     printf("%d ",dp[st-1]);  
  142.     return 0;  
  143. }  
原文地址:https://www.cnblogs.com/si--nian/p/10640845.html