题目链接: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. 量化交易之 tushare

    作为一名老股民,我对金融市场一直都保持长期的关注. 最近我大量接触量化交易相关的一切,发现市场力量还是蛮强大的,6年前的很多设想现在已经彻底变成现实,不得不承认市场从来不会等任何人.想好就要马上行动, ...

  2. C语言Windows程序开发—Windows窗口样式与常用控件样式【第04天】

    (一)Windows窗口(MDICLIENT)样式介绍 /* Windows窗口样式 */ WS_BORDER //带有边框的窗口 WS_CAPTION //带有标题栏的窗口 WS_CHILD //子 ...

  3. makefile = 与 := 的区别

    “=” make会将整个makefile展开后,再决定变量的值.也就是说,变量的值将会是整个makefile中最后被指定的值.看例子: x = foo            y = $(x) bar  ...

  4. codeforces 845A Chess Tourney

    参考:https://blog.csdn.net/zhongyuchen/article/details/77478039 #include <iostream> #include < ...

  5. (转载)深入super,看Python如何解决钻石继承难题

    1.   Python的继承以及调用父类成员 python子类调用父类成员有2种方法,分别是普通方法和super方法 假设Base是基类 class Base(object): def __init_ ...

  6. 【JDK配置原创】JDK(JRE)环境变量配置原理 --费元星

    已经配置了很多次jdk了,每次都是安装网上的教程配的,今天突然想了解了解原理了,整理一下! 参考贴( http://blog.csdn.net/wkupaochuan/article/details/ ...

  7. Delphi实例之一个简易的浏览器的实现

    Delphi实例之一个简易的浏览器的实现 Delphi7的WebBrowser组件提供了很多不错的网页设计的功能,下面做一个简单的浏览器.组件很简单按照下面摆放就行了. 这是运行后的效果 源代码 主页 ...

  8. 云计算之路-阿里云上:“黑色1秒”问题与2009年Xen一个补丁的故事

    在之前对“黑色1秒”问题的分析博文中,我们将最大嫌疑对象锁定在了Xen,在这篇博文我们将从Xen的角度进行分析.也许有人会问,为什么不知道天多高地多厚地去研究不属于自己范围的问题?只因我们对一个问题的 ...

  9. @property, @classmethod基本用法

    @property 废话少说,贴上代码(代码参考@廖雪峰教程) class Student(object): def __init__(self, score): self._score = scor ...

  10. 1034 Head of a Gang (30 分)(图的遍历or并查集)

    dfs #include<bits/stdc++.h> using namespace std; ; int mp[N][N]; int weight[N]; int vis[N]; ma ...