zoukankan      html  css  js  c++  java
  • bzoj4006: [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)这四对情报站连接。

    数据范围与提示

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

    其中有20%的数据,p=2;

    另有20%的数据,p=4。

    题解

    bzoj4774差不多,只不过给定的点集大小不固定,把判断状态是否合法的函数改一下就行了。

    代码

    #include<bits/stdc++.h>
    #define MAXN 3010
    #define INF 0x3f3f3f3f
    namespace IO{
    	char buf[1<<15],*fs,*ft;
    	inline char gc(){return (fs==ft&&(ft=(fs=buf)+fread(buf,1,1<<15,stdin),fs==ft))?0:*fs++;}
    	inline int qr(){
    		int x=0,rev=0,ch=gc();
    		while(ch<'0'||ch>'9'){if(ch=='-')rev=1;ch=gc();}
    		while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=gc();}
    		return rev?-x:x;}
    }using namespace IO;
    using namespace std;
    struct Edge{int t,next,v;}e[MAXN<<1];
    int N,M,P,head[MAXN],cnt,f[MAXN][1<<10],c[12],g[1<<10],num[12],tmp[12];
    bool vis[MAXN];
    queue<int>q;
    inline void Add_Edge(int from,int to,int v){
    	e[++cnt].t=to;e[cnt].next=head[from];head[from]=cnt;e[cnt].v=v;
    	e[++cnt].t=from;e[cnt].next=head[to];head[to]=cnt;e[cnt].v=v;
    }
    inline void Spfa(int S){
    	for(int i=1;i<=N;i++)if(f[i][S]!=INF){
    		q.push(i);vis[i]=1;
    	}
    	while(!q.empty()){
    		int u=q.front();q.pop();vis[u]=0;
    		for(int i=head[u];i;i=e[i].next){
    			int v=e[i].t;
    			if(f[u][S]+e[i].v<f[v][S]){
    				f[v][S]=f[u][S]+e[i].v;
    				if(!vis[v])q.push(v),vis[v]=1;
    			}
    		} 
    	}
    } 
    inline bool Check(int S){
    	memset(tmp,0,sizeof(tmp));
    	for(int i=0;i<P;i++){
    		if((S>>i)&1){
    			tmp[c[i+1]]++;
    		}
    	}
    	for(int i=1;i<=P;i++){
    		if(tmp[i]&&tmp[i]!=num[i])return 0; 
    	}
    	return 1;
    }
    int x,y,z;
    int main(){
    	#ifndef ONLINE_JUDGE
    	freopen("channel.in","r",stdin);
    	freopen("channel.out","w",stdout);
    	#endif
    	N=qr();M=qr();P=qr();
    	for(int i=1;i<=M;i++){
    		x=qr();y=qr();z=qr();
    		Add_Edge(x,y,z); 
    	}
    	memset(f,INF,sizeof(f));
    	memset(g,INF,sizeof(g));
    	for(int i=1;i<=P;i++){
    		c[i]=qr();x=qr();
    		num[c[i]]++;
    		f[x][1<<(i-1)]=0;
    	}
    	for(int j=0,ed=(1<<P);j<ed;j++){
    		for(int i=1;i<=N;i++){
    			for(int k=j&(j-1);k;k=(k-1)&j){
    				f[i][j]=min(f[i][j],f[i][k]+f[i][j-k]);
    			}
    		}
    		Spfa(j);
    		for(int i=1;i<=N;i++)g[j]=min(g[j],f[i][j]);
    	}
    	for(int j=0,ed=(1<<P);j<ed;j++){
    		for(int k=j&(j-1);k;k=(k-1)&j){
    			if(Check(k)&&Check(j-k)){
    				g[j]=min(g[j],g[k]+g[j-k]);
    			}
    		}
    	}
    	printf("%d",g[(1<<P)-1]);
    	return 0;
    }
    
  • 相关阅读:
    CentOS 7 虚拟机的安装
    2 MySQL rpm
    01-在实体类上加了lombok的@Data注解
    02-myBatisPlus的wrapper接口的使用
    2 MySQL rpm 安装 --下载
    1-MySQL介绍
    MySQL的不归路
    电脑型号4 1500 内存大 机械大硬盘
    电脑型号3 1200 大硬盘
    电脑概览 2 1200 固态SSD
  • 原文地址:https://www.cnblogs.com/lrj998244353/p/8847768.html
Copyright © 2011-2022 走看看