洛谷P3264 [JLOI2015]管道连接

https://www.luogu.com.cn/problem/P3264

就跑跑斯坦纳树,然后由于只需要相同的组在一起就行,那么最后还需要合并一下,也就是g[s]=min(g[s],g[t]+g[s^t])其中t和s^t对于每一组来说要么全在里面,要么全不在里面

#include<bits/stdc++.h>
using namespace std;

const int maxl=1e3+10;

int n,m,p,up,inf,ans;
int a[maxl],dy[maxl],msk[maxl];
int f[1<<10][maxl],g[1<<10];
struct ed{int to,l;};
vector<ed> e[maxl];
vector<int> b[11];
bool in[maxl];
queue<int> q; 

inline void prework()
{
	scanf("%d%d%d",&n,&m,&p);
	int u,v,w;
	for(int i=1;i<=m;i++)
	{
		scanf("%d%d%d",&u,&v,&w);
		e[u].push_back(ed{v,w});
		e[v].push_back(ed{u,w});
	}
	for(int i=1;i<=p;i++)
	{
		scanf("%d%d",&u,&v);
		b[u].push_back(i);
		a[i]=v;dy[v]=i;msk[u]|=1<<(i-1);
	}
}

inline bool ck(int s)
{
	int len;
	for(int i=1;i<=10;i++)
	if((msk[i]&s)!=0 && (msk[i]&s)!=msk[i])
		return false;
	return true;
}

inline void spfa(int f[])
{
	int u,v;
	while(!q.empty())
	{
		u=q.front();q.pop();
		for(ed ee:e[u])
		{
			v=ee.to;
			if(f[v]<=f[u]+ee.l)
				continue;
			f[v]=f[u]+ee.l;
			if(!in[v])
			{
				q.push(v);
				in[v]=true;
			}
		}
		in[u]=false;
	}
}

inline void mainwork()
{
	memset(f,0x3f,sizeof(f));
	memset(g,0x3f,sizeof(g));
	up=1<<p;inf=f[0][0];
	for(int i=1;i<=p;i++)
		f[1<<(i-1)][a[i]]=0;
	for(int s=0;s<up;s++)
	{
		for(int i=1;i<=n;i++)
		{
			for(int t=s&(s-1);t;t=(t-1)&s)
				f[s][i]=min(f[s][i],f[t][i]+f[s^t][i]);
			if(f[s][i]<inf)
				q.push(i),in[i]=true;
		}
		spfa(f[s]);
		for(int i=1;i<=n;i++)
			g[s]=min(g[s],f[s][i]);
	}
	for(int s=0;s<up;s++)
		for(int t=s&(s-1);t;t=(t-1)&s)
		if(ck(t) && ck(s^t))
			g[s]=min(g[s],g[s^t]+g[t]);
	ans=g[up-1];
}

inline void print()
{
	printf("%d\n",ans);
}

int main()
{
	prework();
	mainwork();
	print();
	return 0;
}

猜你喜欢

转载自blog.csdn.net/liufengwei1/article/details/107565379