题目链接: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. C语言:类型、运算符、表达式

    看了一天书,有点累了.就写写随笔记录一下今天的复习成果吧. C语言的基本数据类型 数值型:整型数,浮点数,布尔数,复数和虚数. 非数值型:字符. 整数最基本的是int,由此引出许多变式诸如有符号整数s ...

  2. Horner规则求多项式

    /* Horner */ /*多项式:A(x)=a[n]X^n+a[n-1]x^n-1+...+a[1]X^1+a[0]X^0*/ #include <stdio.h> long int ...

  3. UVA11988 Broken Keyboard (a.k.a. Beiju Text)【数组模拟链表】

    参考:https://blog.csdn.net/lianai911/article/details/41831645 #include <iostream> #include <c ...

  4. ubuntu配置机器学习环境(三) opencv 安装

    这里使用脚本安装 一些教程里使用cmake 安装,很容易出错的 使用github上的安装脚本,自动化安装 参考链接 Ubuntu $ cd Ubuntu/2.4 $ chmod +x * # 如果要安 ...

  5. 【转】已有打开的与此 Command 相关联的 DataReader,必须首先将它关闭

    在运用Linq to sql 或者 linq to entity等相关linq技术进行数据库访问操作时,如果发生上述异常是因为是因为.NET內部是使用DataReader作数据存取,DataReade ...

  6. Accept 惊群现象测试perl脚本

    $uname -a Linux debian-11-34 3.16.0-4-amd64 #1 SMP Debian 3.16.7-ckt9-3~deb8u1 (2015-04-24) x86_64 G ...

  7. 「暑期训练」「Brute Force」 Optimal Point on a Line (Educational Codeforces Round 16, B)

    题意 You are given n points on a line with their coordinates $x_i$. Find the point x so the sum of dis ...

  8. 「日常训练」Soldier and Badges (CFR304D2B)

    题意 (Codeforces 546B) 问对一个序列最少需要增减几个1能使其彼此不同. 分析 模拟处理.需要注意的是,尽管题目中说了an<=3000,问题是,如果一群a全是3000呢(滑稽), ...

  9. Qt 使用irrlicht(鬼火)3D引擎

    项目中需要加载简单的3D场景.资深老前辈推荐使用开源小巧的引擎irrlicht. 关于irrlicht,来之百度百科 Irrlicht引擎是一个用C++书写的高性能实时的3D引擎,可以应用于C++程序 ...

  10. 小程序js脚本模块化调用

    可以将一些公共的代码抽离成为一个单独的 js 文件,作为一个模块.模块只有通过 module.exports 或者 exports 才能对外暴露接口. 1. common.js // common.j ...