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 }
  • 相关阅读:
    fish shell version
    golang io.ReadFull
    Unity5 2D Animation
    unity3d vscode
    golang bufio.Scanner
    kafka知识点
    linux clone
    Oracle查询在哪些 存储过程/函数/触发器 等等中包含 指定字符串
    在Oracle中,使用简洁的函数(Function)实现字符串split分割效果
    在Spring中,使用ProxyFactory实现对Cglib代理对象的再次代理
  • 原文地址:https://www.cnblogs.com/Yuzao/p/7197419.html
Copyright © 2011-2022 走看看