首页 > 其他分享 >P7916 [CSP-S 2021] 交通规划 sol-最短路+环形dp

P7916 [CSP-S 2021] 交通规划 sol-最短路+环形dp

时间:2023-09-23 10:22:28浏览次数:43  
标签:int 短路 P7916 sol vis 2021 ll dp dis

P7916 [CSP-S 2021] 交通规划 sol

Statement

传送门

Solution

好题。

发现 \(k\le 2\) 的分值非常多,于是我们考虑从 \(k=2\) 入手。

颜色相同就不用说了,直接染成同一种颜色就行了。

我们考虑其他情况,

就是颜色不相同的情况,我们一定是找了一条路径把这个图给切开了

image

就像这个样子。

于是乎,在求的时候我们把格子变成点建图就可以了。

现在考虑对于其他情况,

可以尝试把平面图转换成最短路或最小割

不难想到可以用 dinic 跑最大流,

就是你把黑色和白色附加点分别连向 \(S,T\),

答案就是整个图的最小割,

也就是最大流。

这样可以做到 \(65\) 分,

如果用高级的网络流算法可以直接 AC。

现在考虑正解,

我们把附加点所分成的空白都看成点,

对于有意义(也就是两边颜色不同)的点,我们发现最终答案所构成的路劲一定是从这里面出发的。

image

图中就有四个点 \(A,B,C,D\)

而 \(A,C\) 是本质相同的,因为他们都是红在蓝的顺时针方向。

我们在这些点之间跑最短路,

希望得到两两配对的最小的距离即为答案。

为什么是两两配对

你可以感性理解一下,也可以去题解区理性证明,

其实画图模拟一下也可以知道。

而且我们需要链接两个 本质不同的点

也就是说肯定不会去连 \(A,C\),

很明显 \(A-C,B-D\) 一定没有 \(A-D,B-C\) 优,

并且我们也不会去连交叉的两条线,

这也很明显吧。

于是我们就有了基础的思路了。

我们先顺时针处理所有的附加点,遇到两个相邻的颜色相同算一个,于是就可以划分成两个点集 \(S,T\),对于每一个 \(S\) ,我们都去跑一边 \(dij\),从而求出了到每一个 \(T\) 的距离。

最后再进行一次环形 dp 算出所有情况的答案就可以了。

建图是有点烦的。

调了一天一夜~

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

const int N=505;
const ll inf=1e16;
int head[N*N],tot=1,n,m,T,s[N],t[N],c[N],id[N*N],cnts,cntt,cnt,k,idx=0;
bool vis[N*N];//都要是 N*N,tot是从1开始!!
ll dis[N*N],dp[N][N],g[N][N];
struct node{
  ll x;
  int p,t;
  bool operator <(const node& rhs) const{
    return p<rhs.p;
  }
}a[N];
struct edge{
  int v,nxt;
  ll w;
}e[(N*N)*8];

int read(){
  int x=0,f=1;char ch=getchar();
  while(!isdigit(ch)){if(ch=='-') f=-1;ch=getchar();}
  while(isdigit(ch)){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
  return x*f;
}

void add(int u,int v,ll w){
  e[++tot]=(edge){v,head[u],w};
  head[u]=tot;
  e[++tot]=(edge){u,head[v],w};
  head[v]=tot;
}

void dij(int st){
  for(int i=0;i<N*N;i++) dis[i]=inf;
  priority_queue<pair<ll,int> > q;
  dis[st]=0;
  q.push(make_pair(0,st));
  memset(vis,false,sizeof(vis));
  while(!q.empty()){
  	int u=q.top().second;q.pop();
  	if(vis[u]) continue;
  	vis[u]=true;
  	for(int i=head[u];i;i=e[i].nxt){
  	  int v=e[i].v;
	  if(dis[v]>dis[u]+e[i].w){
	  	dis[v]=dis[u]+e[i].w;
	  	q.push(make_pair(-dis[v],v));
	  }	
	}
  }
}

int cir(int x){return (x-1)%cnt+1;}
void sol(){
  k=read();
  cnt=0,cnts=0,cntt=0;
  for(int i=1;i<=idx;i++) e[i<<1].w=e[i<<1|1].w=0;
  for(int i=1;i<=k;i++){
  	a[i].x=1ll*read();a[i].p=read();a[i].t=read();
  	e[a[i].p<<1].w=e[a[i].p<<1|1].w=a[i].x;
  }
  sort(a+1,a+k+1);
  if(a[1].t==1&&a[k].t==0) s[++cnts]=a[1].p,c[++cnt]=a[1].p;
  if(a[1].t==0&&a[k].t==1) t[++cntt]=a[1].p,c[++cnt]=a[1].p;
  for(int i=2;i<=k;i++){
  	if(a[i].t==1&&a[i-1].t==0) s[++cnts]=a[i].p,c[++cnt]=a[i].p;
  	if(a[i].t==0&&a[i-1].t==1) t[++cntt]=a[i].p,c[++cnt]=a[i].p; 
  }
  if(cnts==0){puts("0");return;}
  sort(c+1,c+cnt+1);
  for(int i=1;i<=cnt;i++) id[c[i]]=i;
  memset(g,0x7f,sizeof(g));
  memset(dp,0x7f,sizeof(dp));
  for(int i=1;i<=cnts;i++){
  	dij(s[i]);
  	for(int j=1;j<=cntt;j++) g[id[s[i]]][id[t[j]]]=g[id[t[j]]][id[s[i]]]=dis[t[j]];
  }
    //环形dp
  for(int i=1;i<(cnt<<1);i++) dp[i][i+1]=g[cir(i)][cir(i+1)];
  for(int len=4;len<=cnt;len+=2)
    for(int i=1;i<=(cnt<<1)-len+1;i++){
      int j=i+len-1;
      dp[i][j]=dp[i+1][j-1]+g[cir(i)][cir(j)];
      for(int l=i+1;l<j;l+=2)
        dp[i][j]=min(dp[i][j],dp[i][l]+dp[l+1][j]);
	}
  ll ans=inf;
  for(int i=1;i<=cnt;i++) ans=min(ans,dp[i][i+cnt-1]);
  printf("%lld\n",ans);
}

int find(int i,int j){return (i-1)*m+j;}


void wrk(){
  n=read();m=read();T=read();
  idx=(n+m)*2;
  for(int i=1;i<idx;i++) add(i,i+1,0);
  add(idx,1,0);
  for(int i=1;i<n;i++)
    for(int j=1;j<=m;j++){
      ll x;
	  x=1ll*read();
      if(j==1) add(idx+find(i,j),idx-i+1,x);
      else if(j==m) add(idx+find(i,j-1),m+i+1,x);
      else add(idx+find(i,j-1),idx+find(i,j),x);
	}
  for(int i=1;i<=n;i++)
    for(int j=1;j<m;j++){
      ll x=1ll*read();
      if(i==1) add(idx+find(i,j),j+1,x);
      else if(i==n) add(idx+find(i-1,j),2*m+n-j+1,x);//注意是2*m+n!
      else add(idx+find(i-1,j),idx+find(i,j),x);
	}
	 
  while(T--) sol();
}

int main(){
  /*2023.9.23 H_W_Y P7916 [CSP-S 2021] 交通规划 最短路*/ 
  wrk();
  return 0;
}

Conclusion

对于这种平面图上面的问题,我们可以尝试转化成最短路或最小割问题再求解。

图上问题一定要画图模拟分析,也可适当猜一下结论~

整道题与交通规划没有半点关系呵呵。

标签:int,短路,P7916,sol,vis,2021,ll,dp,dis
From: https://www.cnblogs.com/hwy0622/p/17723955.html

相关文章

  • Ubuntu20.04 ping Temporary failure in name resolution问题
    解决步骤vi/etc/systemd/resolved.conf将DNS的注释取消掉并改成8.8.8.8即可参考:https://blog.csdn.net/weixin_43354181/article/details/105352203......
  • Solution -「HDU」Ridiculous Netizens
    Desc.  给定一棵\(N\)个节点无根树,找出满足以下条件的集合\(S\)的数量:\(S\subseteq\{1,\dots,n\}\);\(S\)的导出子图联通;\(\displaystyle\prod_{v\inS}a_v\leqslantM\)。Sol.  点分治,统计包括当前分治中心的集合数量,如果从子树的角度入手会发现并不好做—......
  • SOLIDWORKS二次开发——拓展设计能力与定制化解决方案
    SOLIDWORKS是一款广泛应用于机械设计行业的三维CAD软件,它提供了丰富的功能和工具,满足了企业的基本设计需求。然而,有时候标准软件的功能无法满足特定的要求,这就需要进行二次开发来扩展SOLIDWORKS的功能,制定定制化的解决方案。 1.什么是SOLIDWORKS二次开发?SOLIDWORKS二次开发是......
  • 如何在SOLIDWORKS PDM中快速导出BOM表
    在SOLIDWORKSPDM中,选择装配体后,下方就可以直接看到该装配体的材料明细表,并直接导出CSV文件,在材料明细表里我们可以去定义我们要输出哪些属性信息,但是不能定义BOM表格的表头样式,所以导出材料明细表之后还要再编辑表头信息,才能够做出符合公司规范的BOM表。今天我们介绍一款工具-SO......
  • Exam DP-300: Administering Microsoft Azure SQL Solutions 微软Azure SQL Solutions
    作为该考试的考生,您应具备构建数据库解决方案方面的主题专业知识,这些解决方案旨在支持使用数据库构建的多种工作负载:企业内部SQLServerAzureSQL服务您是一名数据库管理员,负责管理使用SQLServer和AzureSQL服务构建的内部部署和云数据库。作为Azure数据库管理员,您......
  • 2021-2022 ICPC Northwestern European Regional Programming Contest (NWERC 2021)
    A.AccessDenied先问若干次,问出长度,然后再一位一位的问即可。#include<bits/stdc++.h>usingnamespacestd;intinput(){strings;getline(cin,s);if(s=="ACCESSGRANTED")exit(0);intt=0;for(autoi:s){if(i&g......
  • [CSP-J 2021] 插入排序
    题目描述插入排序是一种非常常见且简单的排序算法。小Z是一名大一的新生,今天H老师刚刚在上课的时候讲了插入排序算法。假设比较两个元素的时间为\(\mathcalO(1)\),则插入排序可以以\(\mathcalO(n^2)\)的时间复杂度完成长度为\(n\)的数组的排序。不妨假设这\(n\)个数......
  • The 2021 China Collegiate Programming Contest (Harbin) JBEID
    The2021ChinaCollegiateProgrammingContest(Harbin)JBEIDJ.LocalMinimum模拟题意:一个数当且仅当它是当前列最小值同时也是当且行的最小值它才算入贡献。思路:直接\(for\),预处理出每一行每一列的最小值,然后去\(check\)每一个数。//AConemoretimes//nndbk#inc......
  • 【枚举】【贪心技巧】【集训队互测2021】子集匹配
    题目描述给定\(n,k(2k\geqn)\),二进制中有\(k\)个\(1\)的不超过\(n\)位的数有\(\binom{n}{k}\)个,有\(k-1\)个\(1\)的有\(\binomn{k-1}\)个,后者显然大于等于前者,要求对于每一个\(k\)个\(1\)的数\(x\),都找出一个\(k-1\)位的数\(y\)与之对应,且\(x......
  • SLC SSD重出江湖!Solidigm D7-P5810正式发布:每天65次全盘写入
    如今的SSD,在闪存介质上早已经是TLC遍地走、QLC越来越多,很多玩家非常怀念当年的MLC,甚至是最初的SLC。原因无它,MLC、SLC的可靠性非常高。快科技9月21日消息,Solidigm宣布推出其首款面向数据中心市场的超高速SLCSSD——D7-P5810。它使用了久经考验的144层堆叠3D闪存,但确切地说并......