[JLOI2015]管道连接

题目传送门

分析:
同色点连通挺恶心的
要求全部点连通的话就可以直接斯坦纳树了
同色点连通满足还要考虑异色点可能会共用边使答案更小
于是尝试枚举一个颜色集合的点全部连通,形成斯坦纳树
然后把所有集合拼起来,形成斯坦纳森林
之中有一种方案一定是最小的
枚举子集的子集的子集复杂度是\(O(4^n)\)
总复杂度为\(O(n4^p)\)
开O2跑得过还真离谱

#include
#include
#include
#include
#include
#include

#define maxn 1005
#define maxm 6005
#define INF 0x3f3f3f3f

using namespace std;

inline int getint()
{
	int num=0,flag=1;char c;
	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
	return num*flag;
}

int n,K,m;
int fir[maxn],nxt[maxm],to[maxm],len[maxm],cnt;
long long f[maxn][1<<10],g[1<<10];
bool vis[maxn];
mapM;
int cur;
int c[maxn],id[maxn];

struct node{
	int u;long long w;
	friend bool operator <(node x,node y){return x.w>y.w;}
};
priority_queueQ;

inline void newnode(int u,int v,int w)
{to[++cnt]=v,nxt[cnt]=fir[u],fir[u]=cnt,len[cnt]=w;}
inline void dij(int S)
{
	memset(vis,0,sizeof vis);
	while(!Q.empty())
	{
		int u=Q.top().u;Q.pop();
		if(vis[u])continue;vis[u]=1;
		for(int i=fir[u];i;i=nxt[i])
			if(f[to[i]][S]>f[u][S]+len[i])
				Q.push((node){to[i],f[to[i]][S]=f[u][S]+len[i]});
	}
}

inline long long solve(int t)
{
	for(int i=0;i<(1<

你可能感兴趣的:([JLOI2015]管道连接)