• bzoj 4006: [JLOI2015]管道连接


    Description

    小铭铭最近进入了某情报部门,该部门正在被如何建立安全的通道连接困扰。

    该部门有 n 个情报站,用 1 到 n 的整数编号。给出 m 对情报站 ui;vi 和费用 wi,表示情
    报站 ui 和 vi 之间可以花费 wi 单位资源建立通道。
    如果一个情报站经过若干个建立好的通道可以到达另外一个情报站,那么这两个情报站就
    建立了通道连接。形式化地,若 ui 和 vi 建立了通道,那么它们建立了通道连接;若 ui 和 vi 均
    与 ti 建立了通道连接,那么 ui 和 vi 也建立了通道连接。
    现在在所有的情报站中,有 p 个重要情报站,其中每个情报站有一个特定的频道。小铭铭
    面临的问题是,需要花费最少的资源,使得任意相同频道的情报站之间都建立通道连接。

    Input

    第一行包含三个整数 n;m;p,表示情报站的数量,可以建立的通道数量和重要情报站的数

    量。接下来 m 行,每行包含三个整数 ui;vi;wi,表示可以建立的通道。最后有 p 行,每行包含
    两个整数 ci;di,表示重要情报站的频道和情报站的编号。

    Output

    输出一行一个整数,表示任意相同频道的情报站之间都建立通道连接所花费的最少资源总量。

    Sample Input

    5 8 4
    1 2 3
    1 3 2
    1 5 1
    2 4 2
    2 5 1
    3 4 3
    3 5 1
    4 5 1
    1 1
    1 2
    2 3
    2 4

    Sample Output

    4

    HINT

    选择 (1; 5); (3; 5); (2; 5); (4; 5) 这 4 对情报站连接。


    对于 100% 的数据,0 <ci <= p <= 10; 0 <ui;vi;di <= n <= 1000; 0 <= m <= 3000; 0 <= wi <=

    20000。
     
     
    题解:
    斯坦纳树变式,只需正常跑一边斯坦纳然后再加特判,这题中F[i][k]中第二维k不再表示k这个状态联通
    而表示k状态中,相同频道的站都联通,所以我们最后再合并,避免漏解情况
    可以理解为:斯坦纳跑出来的k是两个块用一些边连起来以后的联通块,而此题中一些边可以去掉,只需满足相同频道联通即可
     1 #include <algorithm>
     2 #include <iostream>
     3 #include <cstdlib>
     4 #include <cstring>
     5 #include <cstdio>
     6 #include <cmath>
     7 using namespace std;
     8 const int N=1005,M=3005;
     9 int gi(){
    10     int str=0;char ch=getchar();
    11     while(ch>'9' || ch<'0')ch=getchar();
    12     while(ch>='0' && ch<='9')str=(str<<1)+(str<<3)+ch-48,ch=getchar();
    13     return str;
    14 }
    15 int head[N],num=0;
    16 struct Lin{
    17     int next,to,dis;
    18 }a[M<<1];
    19 void init(int x,int y,int z){
    20     a[++num].next=head[x];a[num].to=y;a[num].dis=z;head[x]=num;
    21 }
    22 int n,m,col,f[N][1<<10],P=0,tot,INF;
    23 bool vis[N];int q[N*10],mod=N*10;
    24 void spfa(int k){
    25     int t=0,sum=0,x,u;
    26     for(int i=1;i<=n;i++)
    27         if(f[i][k]!=INF)q[++sum]=i,vis[i]=true;
    28     while(t!=sum){
    29         t++;if(t>=mod)t-=mod;x=q[t];
    30         for(int i=head[x];i;i=a[i].next){
    31             u=a[i].to;
    32             if(f[x][k]+a[i].dis<f[u][k]){
    33                 f[u][k]=f[x][k]+a[i].dis;
    34                 if(!vis[u]){
    35                     vis[u]=true;
    36                     sum++;if(sum>=mod)sum-=mod;q[sum]=u;
    37                 }
    38             }
    39         }
    40         vis[x]=false;
    41     }
    42 }
    43 int ans[1<<10];int c[15][15],ts[1<<10];
    44 bool check(int states){
    45     for(int i=1;i<=10;i++){
    46         if(!ts[i])continue;
    47         if((ts[i]&states) && ((states&ts[i])!=ts[i]))return false;
    48     }
    49     return true;
    50 }
    51 void work(){
    52     int x,y,z;
    53     memset(f,127/3,sizeof(f));INF=f[0][0];
    54     n=gi();m=gi();col=gi();
    55     for(int i=1;i<=m;i++){
    56         x=gi();y=gi();z=gi();
    57         init(x,y,z);init(y,x,z);
    58     }
    59     for(int i=1;i<=col;i++){
    60         x=gi();y=gi();
    61         f[y][1<<(P++)]=0;
    62         c[x][++c[x][0]]=P-1;
    63     }
    64     for(int i=1;i<=10;i++)
    65         for(int j=1,tmp=c[i][0];j<=tmp;j++)
    66             ts[i]|=(1<<c[i][j]);
    67     tot=(1<<P)-1;
    68     for(int s=1;s<=tot;s++){
    69         for(int i=1;i<=n;i++)
    70             for(int j=(s-1)&s;j;j=(j-1)&s){
    71                 if(f[i][j]+f[i][s-j]<f[i][s]){
    72                     f[i][s]=f[i][j]+f[i][s-j];
    73                 }
    74             }
    75         spfa(s);
    76     }
    77     memset(ans,127/3,sizeof(ans));
    78     for(int s=1;s<=tot;s++)
    79         for(int i=1;i<=n;i++)
    80             if(f[i][s]<ans[s])ans[s]=f[i][s];
    81     for(int s=1;s<=tot;s++){
    82         if(!check(s)){
    83             ans[s]=INF;
    84             continue;
    85         }
    86         for(int j=(s-1)&s;j;j=(j-1)&s){
    87             if(!check(j))continue;
    88             ans[s]=min(ans[s],ans[j]+ans[s-j]);
    89         }
    90     }
    91     printf("%d
    ",ans[tot]);
    92 }
    93 int main()
    94 {
    95     freopen("pp.in","r",stdin);
    96     work();
    97     return 0;
    98 }
  • 相关阅读:
    【SSH进阶之路】Hibernate映射——一对多关联映射(七)
    深入研究Clang(四) Clang编译器的简单分析
    LLVM每日谈之二十 Everything && Clang driver
    LLVM每日谈之十九 LLVM的第一本系统的书<Getting Started with LLVM Core Libraries>
    session在登录中的使用
    (转)JavaWeb学习总结(十三)——使用Session防止表单重复提交
    网页中自动获取访问用户所在城市的接口插件
    bootstrap新闻模块样式模板
    springmvc的渲染
    springmvc的几点见解
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7197419.html
Copyright © 2020-2023  润新知