• [bzoj 4774]修路


    传送门

    Description 

    该题出现在了FCS省选模拟赛的D4T1

    可以把最后的图分成若干个不相交的部分,显然每个部分都是包含的指定点集合的一个斯坦纳树

    枚举子集合并即可


    Code 

    /*
    	斯坦纳树;O(n*3^n+kE*2^n) 暂且把O(k*E)当成是spfa的复杂度
    	15:15~16:20
    */
    #include<bits/stdc++.h>
    #define ll long long
    #define max(a,b) ((a)>(b)?(a):(b))
    #define min(a,b) ((a)<(b)?(a):(b))
    inline int read()
    {
    	int x=0,f=1;char ch=getchar();
    	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
    	while(ch>='0'&&ch<='9'){x=(x<<3)+(x<<1)+ch-'0';ch=getchar();}
    	return x*f;
    }
    const int MN=10005,MM=20005,inf=0x3f3f3f3f;
    int n,m,k;
    struct edge{int to,w,nex;}e[MM<<1];int hr[MN],en;
    inline void ins(int f,int t,int w)
    {
    	e[++en]=(edge){t,w,hr[f]};hr[f]=en;
    	e[++en]=(edge){f,w,hr[t]};hr[t]=en;
    }
    std::queue<int> q;
    int f[1<<10][MN],g[1<<10],refer[1<<5],ans=inf;
    bool inq[MN];
    void spfa(int *d)
    {
    	register int u,i;
    	while(!q.empty())
    	{
    		u=q.front();q.pop();inq[u]=false;
    		for(i=hr[u];i;i=e[i].nex)
    			if(d[e[i].to]>d[u]+e[i].w)
    			{
    				d[e[i].to]=d[u]+e[i].w;
    				if(!inq[e[i].to]) q.push(e[i].to),inq[e[i].to]=true;
    			}
    	}
    }
    int get(int x)
    {
    	if(x<=k/2) return x*2-1;
    	if(x+k/2>n) return (n-x+1)*2;
    	return x+k/2;
    }
    int main()
    {
    	register int i,j,x,y,S,SS,SSS,s;
    	n=read();m=read();k=read()<<1;SS=1<<k;SSS=1<<(k>>1);
    	while(m--)x=get(read()),y=get(read()),ins(x,y,read());
    	memset(f,0x3f,sizeof f);
    	for(i=1;i<=k;++i) f[1<<i-1][i]=0;
    	for(S=1;S<SS;++S)
    	{
    		for(i=1;i<=n;++i)
    		{
    			for(s=S&(S-1);s;s=(s-1)&S) f[S][i]=min(f[S][i],f[s][i]+f[S^s][i]);
    			if(f[S][i]<inf) q.push(i);
    		}
    		spfa(f[S]);g[S]=inf;
    		for(i=1;i<=n;++i) g[S]=min(g[S],f[S][i]);
    	}
    	for(i=0;i<SSS;++i)
    	{
    		s=0;
    		for(j=0;j<k/2;++j) if(i>>j&1) s|=1<<(j*2);
    		refer[i]=s|(s<<1);
    	}
    	for(S=1;S<SSS;++S)for(s=S&(S-1);s;s=(s-1)&S)
    		g[refer[S]]=min(g[refer[S]],g[refer[s]]+g[refer[S^s]]);
    	printf("%d
    ",g[SS-1]==inf?-1:g[SS-1]);
    	return 0;
    }
    


    Blog来自PaperCloud,未经允许,请勿转载,TKS!

  • 相关阅读:
    C# winform 打包成安装程序(exe)
    gitHub----【Mac】sourcetree连接github,报错:fatal:Authentication failed for'https://git…。或提示password required 解决方案
    python3-----往一个字符串中循环添加数据
    python3.8----从多层嵌套Json中解析所需要的值
    记录一些工作知识
    【转】彻底搞懂 async & defer
    【转】判断JS数据类型的四种方法
    动态表单设计
    封装,继承,多态
    语义化版本
  • 原文地址:https://www.cnblogs.com/PaperCloud/p/bzoj_4774.html
Copyright © 2020-2023  润新知