zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    June 26th 2017 Week 26th Monday
    June 25th 2017 Week 26th Sunday
    June 24th 2017 Week 25th Saturday
    June 23rd 2017 Week 25th Friday
    June 22nd 2017 Week 25th Thursday
    2018最佳网页设计:就是要你灵感爆棚!!!
    图片素材类Web原型制作分享-Pexels
    想要打动HR的心,UX设计师求职信究竟应该怎么写?
    【UXPA大赛企业专访】Mockplus:“设计替代开发”将成为现实
    2018年最好的医疗网站设计及配色赏析
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7197419.html
Copyright © 2011-2022 走看看