USACO4.1 Fence Loops【最小环&边->点转化】
数据不是很大,如果要转换为正常的那种建图方式的话,可以给点进行标号,用一个二维数组存这两条边相交的那个点的标号,方便处理。一定要注意不要同一个点使用不同的编号也不要不同的点使用同一个编号(这不是废话嘛)不展开。
想多说一下一种比较有意思的做法,就是把边看成点,把边权转化为点权。
这样的话,原本的最小环长就变成了一条路径上经过的所有点的点权之和啦。
大概,张这个样子吧:
边是没有权值的,它只表示连通性。
不过由于把边看成了点,所以处理有些特殊:
原本的是指点到点所经过的边权之和的最小值,但边->点之后,就变成了点到点所经过的点权之和的最小值(含点和点),那么在转移的时候,原本的方程式就不能用,因为和都包含了点的点权,所以要减去,应该写成这个样子:
然后就用求最小环就可以了
->
简单说一下求最小环,感觉就是做一遍答案就是。
但是不行啊,因为无法保证和表示的路是不一样的。
转移的时候是枚举,,三重循环的嘛,就在每一次通过转移之前(也就是现在的是靠作为中转站转移过来的)对最小环进行更新,因为和走的路肯定不一样(一个肯定没有经过,一个肯定经过了)
就可以啦。
(如果你会的话,上面的应该都能看懂,不过不会的话可以百度一下,不是很难)
->
另外,有一个很坑的地方,是由于边->点造成的,如果边长成这个样子:
那把边搞成点就成了这个样子:
这是一个环,但是显然这个环是不符合题目要求的,因为题目要的是这种环:
特判一下就可以啦,由于只有,随便怎么搞都可以。

1 /* 2 ID: Starry21 3 LANG: C++ 4 TASK: fence6 5 */ 6 #include<cstdio> 7 #include<algorithm> 8 #include<cstring> 9 using namespace std; 10 #define N 105 11 #define INF 0x3f3f3f3f 12 int n,len[N]/*新图点权*/,ans=INF; 13 int dis[N][N]/*两点间最短距离(floyd)*/,s[N][N]/*直接距离(直接相连的)*/; 14 bool G[N][N]/*邻接矩阵*/,vis[N][N][N]/*判断三条边是否交于一点*/; 15 int tmp[N],ns[5];//辅助输入,见程序 16 int main() 17 { 18 //freopen("fence6.in","r",stdin); 19 //freopen("fence6.out","w",stdout); 20 scanf("%d",&n); 21 for(int p=1;p<=n;p++) 22 { 23 int id;scanf("%d",&id); 24 tmp[0]=id; 25 scanf("%d %d %d",&len[id],&ns[1],&ns[2]); 26 for(int q=1;q<=2;q++) 27 { 28 for(int i=1;i<=ns[q];i++) 29 { 30 int id2;scanf("%d",&id2); 31 G[id][id2]=G[id2][id]=1; 32 tmp[i]=id2;//记录边交于一点的编号 33 for(int j=1;j<i;j++) 34 for(int k=0;k<j;k++) 35 vis[tmp[i]][tmp[j]][tmp[k]]=vis[tmp[i]][tmp[k]][tmp[j]]=vis[tmp[j]][tmp[i]][tmp[k]]=vis[tmp[j]][tmp[k]][tmp[i]]=vis[tmp[k]][tmp[i]][tmp[j]]=vis[tmp[k]][tmp[j]][tmp[i]]=1; 36 } 37 } 38 } 39 memset(dis,0x3f,sizeof(dis)); 40 for(int i=1;i<=n;i++) 41 for(int j=i+1;j<=n;j++) 42 if(G[i][j]) 43 dis[i][j]=dis[j][i]=s[i][j]=s[j][i]=len[i]+len[j]; 44 for(int k=1;k<=n;k++) 45 { 46 for(int i=1;i<=n;i++) 47 if(G[i][k]) 48 for(int j=i+1;j<=n;j++) 49 if(G[k][j]&&!vis[i][j][k]) 50 ans=min(ans,dis[i][j]+s[i][k]+s[k][j]-len[i]-len[j]-len[k]); 51 for(int i=1;i<=n;i++) 52 for(int j=1;j<=n;j++) 53 dis[i][j]=min(dis[i][j],dis[i][k]+dis[k][j]-len[k]); 54 } 55 printf("%d\n",ans); 56 return 0; 57 }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· 分享一个免费、快速、无限量使用的满血 DeepSeek R1 模型,支持深度思考和联网搜索!
· 使用C#创建一个MCP客户端
· 基于 Docker 搭建 FRP 内网穿透开源项目(很简单哒)
· ollama系列1:轻松3步本地部署deepseek,普通电脑可用
· 按钮权限的设计及实现