题目链接: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. linux实现DNS轮询实现负载平衡

    DNS 轮询机制会受到多方面的影响,如:A记录的TTL时间长短的影响:别的 DNS 服务器 Cache 的影响:windows 客户端也有一个DNS Cache.这些都会影响 DNS 轮询的效果.因此 ...

  2. 《史上最简单的MySQL教程》系列分享专栏

    <史上最简单的MySQL教程>系列分享专栏 <史上最简单的MySQL教程>已整理成PDF文档,点击可直接下载至本地查阅https://www.webfalse.com/read ...

  3. 017---Django的中间件解决跨域

    跨域 跨域是什么? 浏览器从一个域名的网页去请求另一个域名的资源的时候,如果不同源.请求的响应结果就会被浏览器的同源策略所拦截 同源策略是什么? 同源:协议 + 域名 + 端口 特点:阻止ajax请求 ...

  4. 三种urllib实现网页下载,含cookie模拟登陆

    coding=UTF-8 import re import urllib.request, http.cookiejar, urllib.parse # # print('-------------- ...

  5. c/c++ 随机数生成

    当程序需要一个随机数时有两种情况下使用: 1.程序中只需使用一次随机数,则调用rand()函数即可 2.程序需要多次使用随机数,那么需要使用srand()函数生成随机数种子在调用rand()函数保证每 ...

  6. 第四模块:网络编程进阶&数据库开发 考核实战

     1.什么是进程?什么是线程? 什么是协程? 进程:正在进行的一个过程或者说一个任务.而负责执行任务则是cpu. 线程:在传统操作系统中,每个进程有一个地址空间,而且默认就有一个控制线程 协程是一种用 ...

  7. Lambda方式左连接有Linq方式左连接

    网上查到的直接使用Join+DefaultIfEmpty的方式是错误的,实际生成SQL是两表先内联接,然后再LEFT JOIN.经过查证,参考资料,最终得到如下两种方式的左连接写法: public v ...

  8. zabbix 语音告警

    之前的文章中已经实现了zabbix 邮件告警和微信告警,生产环境上测试出消息抵达很及时,但是!万一服务器在大半夜突发故障微信.邮件这些通知都是废物了,大晚上还能听到微信通知吗?显然不可能(我的某朋友就 ...

  9. gcc options选项的优化及选择

    gcc options选项的优化 -c和-o都是gcc编译器的可选参数[options] -c表示只编译(compile)源文件但不链接,会把.c或.cc的c源程序编译成目标文件,一般是.o文件.[只 ...

  10. pexpect获取远端命令执行结果

    类比于shell的expect, python中使用pexpect模块来模拟用户和终端交互.有的时候使用pexpect.sendline发送命令后,在各种条件影响下, 可能并不能保证命令在远端服务器执 ...