首页 > 其他分享 >P3577 [POI2014]TUR-Tourism 题解

P3577 [POI2014]TUR-Tourism 题解

时间:2024-02-27 22:13:20浏览次数:23  
标签:pw min 题解 TUR dfs 站点 P3577 节点 dp

考虑在无向图上进行 dfs,可以得到很多棵 dfs 树(因为图不一定连通),这些树形成了一个森林。

然后由任意两点间不存在节点数超过 \(10\) 的简单路径这个限制可以得出这些树的深度都不超过 \(10\),然后可以想到树上状压 dp。

有一个重要的性质,就是无向图 dfs 树上的非树边,一定是回边,所以不存在横叉边。这也是我们状压这些节点的父亲状态的原因。

对于一个节点,我们用一个数(\(0,1,2\))表示这个节点的状态:

  • 用 \(0\) 表示在这个节点上没有建立站点 且 所有已经访问过的且跟这个节点相邻的节点都没有建立站点。

  • 用 \(1\) 表示 在这个节点没有建立站点 但是 存在一个已经访问过的且跟这个节点相邻的节点建立了站点。

  • 用 \(2\) 表示在这个节点上有建立站点。

下面就是动态规划。

我们用 \(dp[i][j]\) 记录一个最小费用。其中 \(j\) 在三进制表示下从低到高的每一位分别表示从根节点到节点 \(i\) 的路径上的每一个节点的状态。

\(dp[i][j]\) 表示现在从根节点到节点 \(i\) 的路径的状态是 \(j\),在所有已经访问过的节点里,除了从根节点到节点 \(i\) 的路径上的节点以外的所有节点都已经满足了题目中的条件,最小费用是多少。

在 dfs 的过程中当访问到一个节点 \(x\) 时,若 \(x\) 是根节点,则 \(dp[x][0]=0,dp[x][1]=\inf,dp[x][2]=c[x]\),否则我们用 \(fa\) 表示 \(x\) 的父亲,\(d_x\) 表示 \(x\) 的深度(根节点深度为 \(0\)),我们枚举每一个 \(dp[fa][i]\) 对 \(x\) 进行转移(也就是刷表法)。

我们先枚举每一个跟 \(x\) 相邻且已经访问过的节点 \(y\)(由前面的性质可以知道这个节点一定是 \(x\) 的祖先),求出两个值 \(S\) 和 \(T\),初始化 \(T=0,S=i\):

  • 若 \(y\) 的状态是 \(2\),则令 \(T=1\)

  • 若 \(y\) 的状态是 \(0\),则令 \(S=S+3^{d_y}\)

下面考虑是否在 \(x\) 建立站点:

  • 若不在 \(x\) 建立站点,可以这样更新:

\[dp[x][i+T\times3^{d_x}]=\min(dp[x][i+T\times3^{d_x}],dp[fa][i]) \]

  • 若在 \(x\) 建立站点,可以这样更新:

\[dp[x][S+2\times3^{d_x}]=\min(dp[x][S+2\times3^{d_x}],dp[fa][i]+c[x]) \]

从父亲转移过了以后下面就继续 dfs,每访问一个 \(x\) 的儿子 \(y\),就会增加很多已经访问过的节点,所以这时候 \(x\) 的 \(dp\) 状态就不对了,我们要用 \(y\) 来更新 \(x\)(因为 \(y\) 的 \(dp\) 状态是正确的)。

对于每一个 \(dp[x][i]\),我们令:

\[dp[x][i]=\min(dp[y][i+3^{d_y}],dp[y][i+2\times 3^{d_y}]) \]

\(\min\) 里的两个值分别代表在 \(y\) 不建立和建立站点的费用。

最终的答案就是每一棵树的 \(\min(dp[root][1],dp[root][2])\) 的和,这里 \(root\) 表示根节点。

到这里差不多就结束了,但是你会发现内存太大了。

由于每一个节点的状态只跟它的父亲和儿子有关,我们可以用这个节点的深度表示这个节点,具体的方法详见代码。

时间复杂度 \(O(3^{10}(n+m))\)。

代码:

#include<bits/stdc++.h>
#define mxn 20003
#define pb push_back
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define rept(i,a,b) for(int i=a;i<b;++i)
using namespace std;
int n,m,ans,pw[13],ds[mxn],c[mxn],dp[13][59049];
vector<int>g[mxn];
bool v[mxn];
void dfs(int x,int d){
	v[x]=1,ds[x]=d;
	if(!d){
		dp[0][0]=0;
		dp[0][1]=1e9;
		dp[0][2]=c[x];
	}else{
		rept(i,0,pw[d+1])dp[d][i]=1e9;
		rept(i,0,pw[d]){
			int t=0,s=i;
			for(int j:g[x])if(v[j]){
				if(i/pw[ds[j]]%3==2)t=1;
				else if(i/pw[ds[j]]%3==0)s+=pw[ds[j]];
			}
			dp[d][i+t*pw[d]]=min(dp[d][i+t*pw[d]],dp[d-1][i]);
			dp[d][s+2*pw[d]]=min(dp[d][s+2*pw[d]],dp[d-1][i]+c[x]);
		}
	}
	for(int i:g[x])if(!v[i]){
		dfs(i,d+1);
		rept(j,0,pw[d+1])dp[d][j]=min(dp[d+1][j+pw[d+1]],dp[d+1][j+pw[d+1]*2]);
	}
}
signed main(){
	pw[0]=1;
	rep(i,1,11)pw[i]=pw[i-1]*3;
	scanf("%d%d",&n,&m);
	rep(i,1,n)scanf("%d",&c[i]);
	for(int i=0,x,y;i<m;++i){
		scanf("%d%d",&x,&y);
		g[x].pb(y),g[y].pb(x);
	}
	rep(i,1,n)if(!v[i]){
		dfs(i,0);
		ans+=min(dp[0][1],dp[0][2]);
	}
	cout<<ans;
	return 0;
}

最后提醒:记得开 O2。

标签:pw,min,题解,TUR,dfs,站点,P3577,节点,dp
From: https://www.cnblogs.com/zifanoi/p/18038525

相关文章

  • CF516E Drazil and His Happy Friends 题解
    题目传送门记\(d=\gcd(n,m)\),发现只有编号在模\(d\)意义下相同的人之间会产生影响,那么有解当且仅当每个剩余系内有至少一个人是快乐的。所以在\(d>b+g\)时直接输出-1即可。对于剩下的情况,先令\(n\leftarrow\fracnd,m\leftarrow\fracmd\),如果\(n<m\)那么把男女交......
  • [ARC140F] ABS Permutation (Count ver.) 题解
    洛谷题面传送门AT题面传送门发现不太好直接求,考虑将\(P\)映射到\(P^{-1}\)上,这样题目中的条件就变成了\(|P_i-P_{i+M}|=1\)。因此我们可以对模\(M\)的每个剩余系做\(M=1\)的情况,然后最后快速幂合并。考虑\(M=1\)的情况怎么做。记\(f_i\)表示\(K=i\)的方案数,......
  • [ARC112F] Die Siedler 题解
    题目传送门人类智慧题。发现\(2\)操作肯定是不劣的,所以能换则换。考虑将手上的牌转换成一个多进制的数,这样\(2\)操作就是其进位方法,\(1\)操作就是将当前的数加上牌包对应的数,答案就是其各位数字之和,不难发现其值为:\[\sum_{i=1}^nc_i\times2^{i-1}\times(i-1)!\]再考......
  • 2024.2.27模拟赛T2题解
    题目有一个神奇的结论\(\foralla<b<c,a\oplusc>min(a\oplusb,b\oplusc)\)然后就可以写出\(n^2\)dp,再用TRIE树优化即可code#include<bits/stdc++.h>usingnamespacestd;#defineN200005#defineintlonglongintn,k1,k2;inta[N],fl[2];constintm......
  • CF1392I Kevin and Grid 题解
    题目传送门\(\large\textbf{Statement.}\)给定两个序列\(a,b\),有一个\(n\timesm\)的网格图,每个点\((i,j)\)上有个权值\(a_i+b_j\),每个点和其上、下、左、右方相邻的点有连边。多次询问,每次给一个阈值\(x\),将图分为权值\(<x\)(蓝色)和\(\gex\)(红色)的两种连通块。一......
  • P10084 [GDKOI2024 提高组] 计算 题解
    题目传送门前置知识:单位根反演先考虑怎么求\(F(x,a,b)\),易得\(\gcd(x^a-1,x^b-1)=x^{\gcd(a,b)}-1\)。所以\(L=m^{\gcd(a,b)}+1,R=m^{\gcd(c,d)}\),然后发现\([L,R]\)中的数模\(m\)后每种余数出现次数相同,下面记其为\(n=\frac{R-L}{m}\)。考虑用生成函数做,易得答案为......
  • [ABC331G] Collect Them All 题解
    洛谷传送门AT传送门\(\textbf{Statement.}\)有\(M\)种颜色,用\(1\simM\)编号,每次抽奖抽中第\(i\)种颜色的概率为\(\frac{c_i}{N}\),其中\(\sumc_i=N\),求抽中每种颜色至少一次的期望次数。\(1\leM\leN\le2\times10^5\)。\(\textbf{Solution.}\)发现直接求不好......
  • [ARC087F] Squirrel Migration 题解
    洛谷题面AT题面如果两条路径不存在交点,则两条路径各选一个端点交换后两路径相交,答案不会变劣。考虑所有路径两两相交的情况,因为图是一棵树,所以这些路径会交于一点。以这个点为根,那么最大的子树大小一定不超过\(\fracn2\),所以这个点是树的重心,每条路径的端点一定在两个不......
  • 个人题解:2024 年湖北省省队选拔集训暨能力测试 第一试
    时与风对每条边进行BFS。二维偏序部分用vector存一下就行了。花神诞日引理:对于\(a<b<c\),\(\min(a\text{XOR}b,b\text{XOR}c)\leqa\text{XOR}c\)。证明:考虑比较\(a,c\)二进制下第一位不同,也就是\(a=(X0\dots)_{(2)},c=(X1\dots)_{2}\)。因为\(b\in(a,c)\)所以......
  • CSP-S 2023 题解
    T1一开始所有密码都没被标记。对于每个输入的状态枚举一遍所有没标记的密码,判断是否可能是正确密码,如果不行就标记一下。最后输出没被标记的密码个数。总共只有\(10^5\)个密码,可以轻松通过。难度:橙。T2见CF1223FStackExterminableArrays题解。难度:蓝。T3大模拟,直......