LA 4080 warfare And Logistics (Dijkstra)
2015-06-22 16:16
316 查看
题意:给出n个结点,m条边的无向正权图。求两两顶点之间路径长度之和C,无路径则长度为L。再求出删除一条边之后C的新值C',使得C'最大。
分析:
直接用Dijkstra或者Floyd暴力枚举均会超时。
可以根据一开始求出来的最短路径树判断将要删除的边是否在树中,若不在,则不需要重新进行一次最短路的计算。
具体实现的话,可以给输入的每条边加一个维度,表示输入的编号。用二维数组E[i][v]表示编号为i的边,是否在顶点v出发的最短路径树中。在求最短路过程中,标记E[i][v]即可。
至于输入重边的问题,可以增加一个del数组,删边的时候标记一下,进行Dijstra跳过删除的边就好了。
分析:
直接用Dijkstra或者Floyd暴力枚举均会超时。
可以根据一开始求出来的最短路径树判断将要删除的边是否在树中,若不在,则不需要重新进行一次最短路的计算。
具体实现的话,可以给输入的每条边加一个维度,表示输入的编号。用二维数组E[i][v]表示编号为i的边,是否在顶点v出发的最短路径树中。在求最短路过程中,标记E[i][v]即可。
至于输入重边的问题,可以增加一个del数组,删边的时候标记一下,进行Dijstra跳过删除的边就好了。
#include<bits/stdc++.h> using namespace std; #define INF 0x3f3f3f3f #define maxn 1005 typedef long long LL; struct HeapNode //优先队列结点 { int d,u; bool operator < (const HeapNode& rhs) const { return d>rhs.d; } }; struct Edge //边 { int from,to,dist,id; }e[maxn]; int L; bool E[maxn][105],del[maxn]; struct Dijkstra { int n,m; //点数和边数 vector<Edge> edges; //边列表 vector<int> G[maxn]; //每个结点出发的边编号(从0开始) bool done[maxn]; //是否已永久标号 int d[maxn]; //s到各个点的距离 int p[maxn]; //最短路中的上一条边 void init(int n) { this->n=n; for(int i=0; i<=n; ++i) G[i].clear(); //清空邻接表 edges.clear();//清空边表 } void addEdge(int from,int to,int dist,int id) { edges.push_back((Edge) { from,to,dist,id }); m=edges.size(); G[from].push_back(m-1); } LL dijkstra(int s,bool flag) //求s到所有点的最短距离 { priority_queue<HeapNode> Q; LL c=0; for(int i=0; i<=n; ++i) d[i]=INF; d[s]=0; memset(done,0,sizeof(done)); Q.push((HeapNode) { 0,s }); while(!Q.empty()) { HeapNode x=Q.top(); Q.pop(); int u=x.u; if(done[u]) continue; done[u]=1; for(int i=0; i<G[u].size(); ++i) { Edge& e=edges[G[u][i]]; if(del[e.id]) continue; if(d[e.to]>d[u]+e.dist) { d[e.to]=d[u]+e.dist; p[e.to]=e.id; if(flag) E[e.id][s]=1; Q.push(HeapNode {d[e.to],e.to}); } } } for(int i=1;i<=n;++i) if(d[i]!=INF) c+=d[i]; else c+=L; return c; } void output(int s,int e,vector<int>& path) { int pos=e; while(1) { path.push_back(pos); if(pos==s) break; pos=p[pos]; } } }; Dijkstra D; LL W[105]; int main() { int n,m,i,j; while(~scanf("%d%d%d",&n,&m,&L)) { memset(E,0,sizeof(E)); memset(del,0,sizeof(del)); D.init(n); for(i=1; i<=m; ++i){ int x,y,z; scanf("%d%d%d",&x,&y,&z); D.addEdge(x,y,z,i); D.addEdge(y,x,z,i); } LL c=0,c1=0,tem; for(i=1;i<=n;++i) {W[i]=D.dijkstra(i,1);c+=W[i];} for(i=1;i<=m;++i){ del[i]=1,tem=0; for(j=1;j<=n;++j){ if(E[i][j]) tem+=D.dijkstra(j,0); else tem+=W[j]; } del[i]=0; c1=max(c1,tem); } printf("%lld %lld\n",c,c1); } return 0; }
相关文章推荐
- 地图两点之间获取距离公式
- NetRouter开发板---基于7620a开源openwrt开发板系列教程(一)
- angular依赖注入的理解(转)
- C#中的里氏替换原则
- Stata编程运用-运用递归函数列示文件夹内所有文件
- 验证码图片生成以及页面取得
- 两种方式实现类似qq搜索的切换
- C++静态局部对象
- linux sysfs下创建文件
- 上传excel文件
- PL/SQL Developer 导出csv文件,用excel打开中文显示乱码
- 散列表的查找代码实现
- C语言源字符集与执行字符集
- C#中as是什么含义?is是什么含义? is与as运算符
- java,数据类型
- 两个乒乓球队进行比赛,各出3人。
- HDU 5273 Dylans loves sequence
- ZABBIX作集中式NGINX性能监控的注意要点
- 这题实在不知道起啥名好了
- 各种集合遍历