题目链接:http://acm.fzu.edu.cn/problem.php?pid=2271

题目中说每条边的边权都是[1,10]之间的整数,这个条件非常关键!以后一定要好好读题啊……

做10次循环,第i次循环加边权为i的边,如果这条边小于当前两点间最短路,就加边,更新两点距离;否则就不要这个边。

每次循环过后,做一次Floyd。至多做10次Floyd。

有一个猜想,比赛的时候就想到了:从小到大加边,如果这个边比这两点之间的最短距离小,就要,否则就不要。这个猜想不会证……

但是只想到了每次更改距离以后都做一次Floyd,没有想到一块加权值相同的边,然后再做Floyd。这里就假设上面的猜想是正确的,然后证明一下统一做Floyd的方法也是正确的吧。

假设dis[][]维护着两点间的最短距离。

首先,对于未经优化的方法,如果有一条边加入了,说明这条边的权比两点的最短路短,如果没有随时维护,只维护到了上次权值不同的最后一条边,由于dis随着维护是越来越小的,所以现在的dis也显然大于这个边权,因此对于没有优化的方法,这条边会加进去。

然后,对于未经优化的方法,如果有一条边没有加入,说明这条边的权w不比两点的最短路短,如果没有随时维护,只维护到了上次权值不同的最后一条边,由于用[1,w-1]的边构成的最短路已经得到,假设这条权值是w的边在优化后会加入,也就是说当前的dis>w,而优化以前没有加入,说明dis'<=w,所以意思就是,加入了一些权值为w的边以后,dis变得<=w了,那这个dis'只能是=w了。既然是权值为w的最短路,要么是用权值为w的边得到的,那此时dis应该也=w了,因为每遇到一个w的边都会更新距离。要么是用[1,w-1]的边构成的,那这个在[1,w-1]之后就应该已经维护出来了。这两种情况都与dis>w矛盾。所以假设失败,这条边在优化以后还是不会加入。

所以加不加入在优化前后是一样的。

#include<cstdio>
#include<cstring> const int maxn=;
const int maxm=;
const int INF=0x3f3f3f3f; struct Edge
{
int u,v,w;
}edge[maxm];
int dis[maxn][maxn]; int main()
{
int t;
scanf("%d",&t);
for (int cas=;cas<=t;cas++)
{
int n,m;
scanf("%d%d",&n,&m);
for (int i=;i<m;i++)
{
scanf("%d%d%d",&edge[i].u,&edge[i].v,&edge[i].w);
}
memset(dis,INF,sizeof(dis));
for (int i=;i<=n;i++) dis[i][i]=;
int ans=;
for (int z=;z<=;z++)
{
for (int e=;e<m;e++)
{
if (edge[e].w==z)
{
int u=edge[e].u;
int v=edge[e].v;
if (z<dis[u][v])
{
dis[u][v]=z;
dis[v][u]=z;
ans++;
}
}
}
for (int k=;k<=n;k++)
for (int i=;i<=n;i++)
for (int j=;j<=n;j++)
if (dis[i][k]+dis[k][j]<dis[i][j])
dis[i][j]=dis[i][k]+dis[k][j];
}
printf("Case %d: %d\n",cas,m-ans);
}
return ;
}

另外还有一种更神的做法,只需要做一次Floyd。

首先,删掉重边和自环。然后剩下的边做一次Floyd,在做的过程中被松弛过的边都可以删去。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std; const int maxn=;
const int INF=0x3f3f3f3f;
int G[maxn][maxn];
int dis[maxn][maxn];
bool vis[maxn][maxn]; int main()
{
int t;
scanf("%d",&t);
for (int cas=;cas<=t;cas++)
{
memset(G,INF,sizeof(G));
memset(dis,INF,sizeof(dis));
memset(vis,false,sizeof(vis));
int n,m;
scanf("%d%d",&n,&m);
int ans=;
for (int i=;i<m;i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
if (G[u][v]<INF||u==v) ans++;
if (w<G[u][v]&&u!=v) G[u][v]=G[v][u]=w;
}
for (int i=;i<=n;i++)
for (int j=;j<=n;j++)
dis[i][j]=G[i][j];
for (int k=;k<=n;k++)
for (int i=;i<=n;i++)
for (int j=;j<=n;j++)
{
if (dis[i][k]+dis[k][j]<=dis[i][j])
{
dis[i][j]=dis[i][k]+dis[k][j];
vis[i][j]=true;
}
}
for (int i=;i<=n;i++)
for (int j=i+;j<=n;j++)
{
if (vis[i][j]&&G[i][j]!=INF) ans++;
}
printf("Case %d: %d\n",cas,ans);
}
return ;
}

[fzu 2271]不改变任意两点最短路至多删的边数的更多相关文章

  1. 2018中国大学生程序设计竞赛 - 网络选拔赛 hdu Tree and Permutation 找规律+求任意两点的最短路

    Tree and Permutation Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Oth ...

  2. 【算法】单源最短路径和任意两点最短路径总结(补增:SPFA)

    [Bellman-Ford算法] [算法]Bellman-Ford算法(单源最短路径问题)(判断负圈) 结构: #define MAX_V 10000 #define MAX_E 50000 int ...

  3. AOJ GRL_1_C: All Pairs Shortest Path (Floyd-Warshall算法求任意两点间的最短路径)(Bellman-Ford算法判断负圈)

    题目链接:http://judge.u-aizu.ac.jp/onlinejudge/description.jsp?id=GRL_1_C All Pairs Shortest Path Input ...

  4. HDU 2376 树形dp|树上任意两点距离和的平均值

    原题:http://acm.hdu.edu.cn/showproblem.php?pid=2376 经典问题,求的是树上任意两点和的平均值. 这里我们不能枚举点,这样n^2的复杂度.我们可以枚举每一条 ...

  5. 图算法之Floyd-Warshall 算法-- 任意两点间最小距离

    1.Floyd-Warshall 算法 给定一张图,在o(n3)时间内求出任意两点间的最小距离,并可以在求解过程中保存路径 2.Floyd-Warshall 算法概念 这是一个动态规划的算法. 将顶点 ...

  6. JAVA 计算地球上任意两点(经纬度)距离

    /** * 计算地球上任意两点(经纬度)距离 * * @param long1 * 第一点经度 * @param lat1 * 第一点纬度 * @param long2 * 第二点经度 * @para ...

  7. caioj 1237: 【最近公共祖先】树上任意两点的距离 在线倍增ST

    caioj 1237: [最近公共祖先]树上任意两点的距离 倍增ST 题目链接:http://caioj.cn/problem.php?id=1237 思路: 针对询问次数多的时候,采取倍增求取LCA ...

  8. php根据地球上任意两点的经纬度计算两点间的距离 原理

    地球是一个近乎标准的椭球体,它的赤道半径为6378.140千米,极半径为6356.755千米,平均半径6371.004千米.如果我们假设地球是一个完美的球体,那么它的半径就是地球的平均半径,记为R.如 ...

  9. HDU 5723 Abandoned country(kruskal+dp树上任意两点距离和)

    Problem DescriptionAn abandoned country has n(n≤100000) villages which are numbered from 1 to n. Sin ...

随机推荐

  1. Java学习笔记十四:如何定义Java中的类以及使用对象的属性

    如何定义Java中的类以及使用对象的属性 一:类的重要性: 所有Java程序都以类class为组织单元: 二:什么是类: 类是模子,确定对象将会拥有的特征(属性)和行为(方法): 三:类的组成: 属性 ...

  2. 《PHP内核探索系列文章》系列分享专栏

    <PHP内核探索系列文章>已整理成PDF文档,点击可直接下载至本地查阅 简介 PHP内核探索系列文章收藏夹收藏有关PHP内核方面的知识的文章,对PHP高级进阶的朋友提供PHP内核方面的知识 ...

  3. POJ1659 可图性判定

    Frogs' Neighborhood Time Limit: 5000MS   Memory Limit: 10000K Total Submissions: 10660   Accepted: 4 ...

  4. C# 实现窗口无边框,可拖动效果

    #region 无边框拖动效果 [DllImport("user32.dll")]//拖动无窗体的控件 public static extern bool ReleaseCaptu ...

  5. R语言绘图:在地图上绘制散点图

    使用ggplot2在地图上绘制散点图 ######*****绘制散点图代码*****####### options(baidumap.key = '**************') #设置密钥 bei ...

  6. python2.7练习小例子(七)

        7):题目:将一个列表的数据复制到另一个列表中.     程序分析:使用列表[:].     程序源代码: #!/usr/bin/python # -*- coding: UTF-8 -*- ...

  7. Hive 复杂数据类型的使用

    Hive复杂数据类型 1.Array数据类型的使用 1.1.创建数据库表,以array作为数据类型 hive (hive_demo1)> create table stu_test(name a ...

  8. oracle 11g XE 学习版添加scott用户方法全步骤

    安装企业版的orcale是不是太费时费力了?若只是学习用途的话,不妨试试轻便版的XE版本,同样是官网下载的,但是这个安装起来比完整版简便多了. 首先,你得先安装好orcale 11g XE 版本:(这 ...

  9. Django调试models输出的SQL语句

    django1.3在shell下,调试models变得更为简单了,不用像之前的版本,手工去调用django query,才能打印出之前的代码是执行的什么SQL语句. 1.3开始只需在settings. ...

  10. Linux下的调试工具

    Linux下的调试工具 随着XP的流行,人们越来越注重软件的前期设计.后期的实现,以及贯穿于其中的测试工作,经过这个过程出来的自然是高质量的软件.甚至有人声称XP会淘汰调试器!这当然是有一定道理的,然 ...