zoukankan      html  css  js  c++  java
  • 【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;
    }
    
    
  • 相关阅读:
    Linux下sed,awk,grep,cut,find学习笔记
    Python文件处理(1)
    KMP详解
    Java引用详解
    解决安卓中页脚被输入法顶起的问题
    解决swfupload上传控件文件名中文乱码问题 三种方法 flash及最新版本11.8.800.168
    null id in entry (don't flush the Session after an exception occurs)
    HQL中的Like查询需要注意的地方
    spring mvc controller间跳转 重定向 传参
    node to traverse cannot be null!
  • 原文地址:https://www.cnblogs.com/cjyyb/p/9670137.html
Copyright © 2011-2022 走看看