• 【BZOJ4006】管道连接(动态规划,斯坦纳树)


    题面

    BZOJ
    洛谷

    题解

    这题区别不是很大吧。
    基本上拿过来改一下就做完了。

    #include<iostream>
    #include<cstdio>
    #include<cstdlib>
    #include<cstring>
    #include<cmath>
    #include<algorithm>
    #include<vector>
    #include<queue>
    #include<map>
    using namespace std;
    #define ll long long
    #define MAX 1100
    inline int read()
    {
    	int x=0;bool t=false;char ch=getchar();
    	while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
    	if(ch=='-')t=true,ch=getchar();
    	while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
    	return t?-x:x;
    }
    int n,m,p;
    struct Line{int v,next,w;}e[MAX<<3];
    int h[MAX],cnt=1;
    inline void Add(int u,int v,int w){e[cnt]=(Line){v,h[u],w};h[u]=cnt++;}
    int f[1<<10][MAX],g[1<<10];
    bool vis[MAX];
    queue<int> Q;
    map<int,int> M;
    int fz[MAX],St[20],G[20];
    void SPFA(int *f)
    {
    	while(!Q.empty())
    	{
    		int u=Q.front();Q.pop();
    		for(int i=h[u];i;i=e[i].next)
    			if(f[e[i].v]>f[u]+e[i].w)
    			{
    				f[e[i].v]=f[u]+e[i].w;
    				if(!vis[e[i].v])Q.push(e[i].v),vis[e[i].v]=true;
    			}
    		vis[u]=false;
    	}
    }
    bool check(int s)
    {
    	for(int i=1;i<=p;++i)
    		if((s&G[i])!=0&&(s&G[i])!=G[i])
    			return false;
    	return true;
    }
    int main()
    {
    	n=read();m=read();p=read();
    	memset(f,63,sizeof(f));memset(g,63,sizeof(g));
    	for(int i=1;i<=m;++i)
    	{
    		int u=read(),v=read(),w=read();
    		Add(u,v,w);Add(v,u,w);
    	}
    	for(int i=1;i<=p;++i)
    	{
    		int c=read(),d=read();
    		fz[d]=c;M[d]=i-1;St[i]=d;
    		f[1<<(i-1)][d]=0;
    	}
    	for(int i=1;i<=p;++i)
    		for(int j=1;j<=p;++j)
    			if(fz[St[i]]==fz[St[j]])
    				G[i]|=1<<M[St[j]];
    	int S=1<<p;
    	for(int i=0;i<S;++i)
    	{
    		for(int j=1;j<=n;++j)
    		{
    			for(int k=i&(i-1);k;k=(k-1)&i)
    				f[i][j]=min(f[i][j],f[k][j]+f[i^k][j]);
    			if(f[i][j]<=1e9)Q.push(j),vis[j]=true;
    		}
    		SPFA(f[i]);
    		for(int j=1;j<=n;++j)g[i]=min(g[i],f[i][j]);
    	}
    	for(int i=0;i<S;++i)
    		for(int t=(i-1)&i;t;t=(t-1)&i)
    			if(check(t)&&check(i^t))
    				g[i]=min(g[i],g[t]+g[i^t]);
    	printf("%d
    ",g[S-1]<=1e9?g[S-1]:-1);
    	return 0;
    }
    
    
  • 相关阅读:
    python 模块和包以及他们的导入关系
    python time,random,os,sys,序列化模块
    python 可迭代对象,迭代器和生成器,lambda表达式
    python之拷贝(深浅)
    python 内置函数
    python 函数的递归
    python 装饰器
    python 函数基础知识整理
    @清晰掉 string.h之基础堵漏
    C和C++之间库的互相调用
  • 原文地址:https://www.cnblogs.com/cjyyb/p/9670137.html
Copyright © 2020-2023  润新知