HDU 2433 最短路
来源:互联网 发布:维多利亚贝克汉姆知乎 编辑:程序博客网 时间:2024/05/01 17:18
////这道题是一道很巧妙的最短路。题目大致的意思就是给定一张无向图,枚举每条边删去,求剩下的图中每个////点对距离之和。//////2433 Travel 删边+最短路之和(预处理桥边)★★★//////注意处理重边//这道题目标程的关键在于两点,第一点在于把所有的最近点对拆分成n个顶点到剩余点的n棵最短路径树,//这样子把整体的不容易去表示的拆分成n个点去跑最短路,使得简化,//这样这道题目就已经简化成了通过某一个顶点枚举删去一条边,求剩下的最短路之和,第二点就是在不必每删去//一条求一次最短路,求出求出最短路径树之后有n-1条边存在于树上,删去其他的边没有影响。这个问题就拆分成//了预处理n棵最短路径树,总共存在n*n-1边 然后跑这么多次最短路,复杂度降为了 n*n*m.//总结一下,将一个整体分拆成一些部分,对每个部分先进行预处理。这样通过枚举最短路径树上的边,这样//子就大大减少了重复计算的次数。对最短路的理解还不够透彻。//标程算法:仍然使用上面的思路,但要作一些预处理。对每个顶点u求一次单源最短路,把求得的结果称作u的最//短路径树,并用数组记录所有点到 其他所有顶点的路径的和。若被破坏的公路不在该最短路径树上,则从u出发//的所有最短路径的总和就是u到该树上的所有顶点的路径的总和,因为刚刚记录了这个 数值,因此花费O(1)时间//就能返回结果。否则,删除被破坏的公路后,//重新通过BFS计算从u出发的所有最短路径的总和,//还要判断被破坏的公路在不在这条最短路径树上。//所以只能在每次删除边的时候,做一些改变。//具体的做法是://对每一个点求一次最短路,并将其求和,保存在一个数组里头,定为sum[i],i表示着一个点到所有其他点最短路//之和。//并将这些和相加 ans = sum[1] + …… + sum[n];//然后,删除一条边,其顶点暂定为u,v,对这条边的一个顶点u在一次求最短路,如果这个点,不能到达这条边的//另一个点v,则 直接输出INF如果,能够到达,则对v也求一次最短路,对于u,v两点来说,求得u到每一个点的最//短路之和sum_u,求得v到每一个点的最短路之和sum_v,//最后结果为: ans = ans + sum_u + sum_v - sum[u] - sum[v];(我觉得这么写不大对吧)#include<iostream>#include<cstring>#include<cstdio>#include<cstdlib>#include<algorithm>#include<queue>#define maxn 200#define maxm 8000#define inf 80000using namespace std;//去掉桥边的处理就对了,好像是我桥边处理的问题。int g[maxn][maxn];bool vis[maxn];int head[maxn],low[maxn];int n,m,cnt,time;bool flag[maxn][maxn][maxn];///i,u,v;点i用到边u,v;struct Edge{ int from,to,next; bool sign;}edge[2*maxm];void addedge(int a,int b){ edge[cnt].from=a; edge[cnt].to=b; edge[cnt].next=head[a]; head[a]=cnt++; edge[cnt].sign=false;}void dfs(int u,int fa){ vis[u]=true; low[u]=time++; for(int i=head[u];~i;i=edge[i].next) { int v=edge[i].to; if(v==fa) continue; if(!vis[v]) dfs(v,u); low[u]=min(low[u],low[v]); }}void tarjan(){ time=0; memset(low,-1,sizeof(low)); dfs(1,1);}int cost[maxn][maxn];int d[maxn];bool used[maxn];int tree[maxn];int spfa( int s )//用处理单源最短路径,但是还要记录用上的边。{ int i,now; for( i=1;i<=n;++i ) { d[i]=inf; used[i]=false; } d[s]=0; queue <int> q; q.push(s); used[s] = true; while(!q.empty()) { now = q.front(); q.pop(); used[now] = false; for(i = 1; i <= n; i++) { if(d[i] > d[now] + cost[now][i])///这里的话算是用上这条边了么。。。 { flag[s][now][i]=true; d[i] = d[now] + cost[now][i]; if(used[i] == 0) { q.push(i); used[i] = true; } } } } int all=0; for(int i=1;i<=n;i++) all+=d[i]; return all;}int spfa2( int s )//用处理单源最短路径,但是还要记录用上的边。{ int i,now; for( i=1;i<=n;++i ) { d[i]=inf; used[i]=false; } d[s]=0; queue <int> q; q.push(s); used[s] = true; while(!q.empty()) { now = q.front(); q.pop(); used[now] = false; for(i = 1; i <= n; i++) { if(d[i] > d[now] + cost[now][i])///这里的话算是用上这条边了么。。。 { d[i] = d[now] + cost[now][i]; if(used[i] == 0) { q.push(i); used[i] = true; } } } } int all=0; for(int i=1;i<=n;i++) all+=d[i]; return all;}struct node{ int u,v;}E[maxm];bool ans[maxm];bool index[maxm];void init(){ for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) cost[i][j]=inf; for(int i=1;i<=n;i++) cost[i][i]=0;}void build(){ for(int i=1;i<=m;i++) { int x=E[i].u; int y=E[i].v; cost[x][y]=cost[y][x]=1; }}int main(){ while(scanf("%d%d",&n,&m)!=EOF) { init(); memset(flag,false,sizeof(flag)); memset(head,-1,sizeof(head)); memset(vis,false,sizeof(vis)); cnt=0; memset(index,false,sizeof(index)); memset(g,0,sizeof(g)); int tempa,tempb; for(int i=1;i<=m;i++) { scanf("%d%d",&tempa,&tempb); g[tempa][tempb]++; g[tempb][tempa]++; addedge(tempa,tempb); addedge(tempb,tempa); cost[tempa][tempb]=cost[tempb][tempa]=1; E[i].u=tempa; E[i].v=tempb; } for(int i=1;i<=m;i++) { int x=E[i].u; int y=E[i].v; if(g[x][y]>1) index[i]=true; } int weight=0; for(int i=1;i<=n;i++) { tree[i]=spfa(i); weight+=tree[i]; } if(weight>=inf) { for(int i=1;i<=m;i++) puts("INF"); continue; } tarjan(); for(int i=0;i<cnt;i++) { int x=edge[i].from; int y=edge[i].to; if(low[x]!=low[y]) edge[i].sign=true; } memset(ans,false,sizeof(ans)); for(int i=0;i<cnt;i++) { if(edge[i].sign) { int temp=i/2+1; if(!index[temp]) ans[temp]=true; } } for(int i=1;i<=m;i++) {// if(ans[i])//桥的处理去掉就过了,应该是桥的处理的问题。// {// puts("INF");continue;// } if(index[i]) { printf("%d\n",weight); continue; } int x=E[i].u; int y=E[i].v; init(); build(); cost[x][y]=cost[y][x]=inf;///建边 int rees=0; for(int j=1;j<=n;j++) { if(flag[j][x][y]||flag[j][y][x]) { int temp=spfa2(j); rees+=temp; } else rees+=tree[j]; } if(rees>=inf) puts("INF"); else printf("%d\n",rees); } }}
0 0
- HDU 2433 最短路
- HDU 2433 最短路
- hdu 2433 Travel 最短路
- hdu 2433 Travel 最短路+预处理
- hdu 2433 最短路树
- Hdu 2433 Travel 删边+最短路之和
- 【HDU】2433 Travel 最短路树优化
- HDU 2433 Travel 最短路SPAF
- hdu 2433 Travel 最短路 dijkstra算法。
- HDU 2433 Travel 最短路树
- HDU 2433 Travel 最短路应用
- HDU - 2433 Travel (最短路树)
- HDU-2433 Travel(最短路[Dijkstra])
- HDU 2433 Travel 枚举+最短路
- 【hdu】2433 Travel【最短路删边】
- HDU 2433 Travel 最短路树
- 最短路 2544hdu
- HDU 2544 最短路
- 【图像加密】图像处理之Logistic混沌置乱加密
- Head_First_Python学习笔记(三)
- 下载apk文件在/data/data/packagename/files/目录下,如何安装成功
- jq+json+ajax demo
- Android中LOG机制详解(上)
- HDU 2433 最短路
- PopupWindow工作笔记
- ubuntu14.04安装Angularjs
- IOS_月薪10k以上知识大总结
- Android常用工具类(收藏)
- Bootstrap栅格系统研究
- IntelliJ IDEA 将 Maven 构建的 Java 项目打包
- HDU3191 次短路条数
- 十进制转化为其他进制(C语言)