poj 3255(次短路)
2015-01-18 13:41
295 查看
题意:给出n个点,m条边,求从顶点1到顶点n的次短路。
分析:首先可以知道,次短路应是在最短路的某个顶点处绕了出去,然后又回到最短路的某个顶点,而且只会绕一次(绕多次的距离肯定比绕一次的大)。再考虑次短路上的两个相邻点i和j,用d1[i]表示从源点1到i的最短距离,用d2[j]表示从j到汇点n的最短距离,那么当i和j在次短路与最短路重合的部分(即没绕出去的那部分)时,d[i]+w[i][j]+d[j]就是最短路的距离,当i或j有一个点处于绕出去的那部分时,d[i]+w[i][j]+d[j]就是次短距离。
因此,我们可以先求出所有的d1[i]和d2[j],再枚举每一条边,求出恰比最短距离大的那个d[i]+w[i][j]+d[j],也即是所求解。
代码如下:
下面这个代码的思想是:到某个顶点v的次短路,要么是到另一个顶点u的次短路再加上u->v这条边,要么是到u的最短路再加上u->v这条边,因此所需要求的就是到所有顶点的最短路和次短路。于是在代码中不仅要记录下最短距离,还要记录下次短距离,并不断维护更新这两个距离(其实我也不太明白,照着模板敲的,程序运行时间比上一个代码要快一点~~~~~)
代码如下:
分析:首先可以知道,次短路应是在最短路的某个顶点处绕了出去,然后又回到最短路的某个顶点,而且只会绕一次(绕多次的距离肯定比绕一次的大)。再考虑次短路上的两个相邻点i和j,用d1[i]表示从源点1到i的最短距离,用d2[j]表示从j到汇点n的最短距离,那么当i和j在次短路与最短路重合的部分(即没绕出去的那部分)时,d[i]+w[i][j]+d[j]就是最短路的距离,当i或j有一个点处于绕出去的那部分时,d[i]+w[i][j]+d[j]就是次短距离。
因此,我们可以先求出所有的d1[i]和d2[j],再枚举每一条边,求出恰比最短距离大的那个d[i]+w[i][j]+d[j],也即是所求解。
代码如下:
#include <cstdio> #include <stack> #include <set> #include <iostream> #include <string> #include <vector> #include <queue> #include <functional> #include <cstring> #include <algorithm> #include <cctype> #include <string> #include <map> #include <iomanip> #include <cmath> #define LL long long #define ULL unsigned long long #define SZ(x) (int)x.size() #define Lowbit(x) ((x) & (-x)) #define MP(a, b) make_pair(a, b) #define MS(arr, num) memset(arr, num, sizeof(arr)) #define PB push_back #define F first #define S second #define ROP freopen("input.txt", "r", stdin); #define MID(a, b) (a + ((b - a) >> 1)) #define LC rt << 1, l, mid #define RC rt << 1|1, mid + 1, r #define LRT rt << 1 #define RRT rt << 1|1 #define BitCount(x) __builtin_popcount(x) #define BitCountll(x) __builtin_popcountll(x) #define LeftPos(x) 32 - __builtin_clz(x) - 1 #define LeftPosll(x) 64 - __builtin_clzll(x) - 1 const double PI = acos(-1.0); const int INF = 0x3f3f3f3f; using namespace std; const double eps = 1e-8; const int MAXN = 300 + 10; const int MOD = 1000007; const int N=5010; const int M=200010; const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; typedef pair<int, int> pii; int n,m,d1 ,d2 ; int u[M],v[M],w[M],first ,next[M]; bool vis ; void build() { int i,j,t=m<<1; memset(first,-1,sizeof(first)); for (i=0;i<t;i+=2){ scanf("%d%d%d",u+i,v+i,w+i); next[i]=first[u[i]]; first[u[i]]=i; u[i+1]=v[i]; v[i+1]=u[i]; w[i+1]=w[i]; next[i+1]=first[u[i+1]]; first[u[i+1]]=i+1; } } void dij(int s,int d[]) { int i,j; memset(vis,false,sizeof(vis)); priority_queue<pii,vector<pii>,greater<pii> > q; for (i=1;i<=n;d[i++]=INF); d[s]=0; q.push(make_pair(d[s],s)); while(!q.empty()) { pii t=q.top(); q.pop(); int pos=t.second, val=t.first; if (d[pos]<val) continue; vis[pos]=true; for (i=first[pos];i!=-1;i=next[i]) if (!vis[v[i]]) { if (d[v[i]]>d[pos]+w[i]){ d[v[i]]=d[pos]+w[i]; q.push(make_pair(d[v[i]],v[i])); } } } } int main() { int i,j; while(~scanf("%d%d",&n,&m)) { int a,b,c; build(); dij(1,d1); dij(n,d2); int ans=INF; for (i=1;i<=n;i++) for (j=first[i];j!=-1;j=next[j]) { int t=d1[u[j]]+w[j]+d2[v[j]]; if (t>d1 && t<ans) ans=t; } cout<<ans<<endl; } }
下面这个代码的思想是:到某个顶点v的次短路,要么是到另一个顶点u的次短路再加上u->v这条边,要么是到u的最短路再加上u->v这条边,因此所需要求的就是到所有顶点的最短路和次短路。于是在代码中不仅要记录下最短距离,还要记录下次短距离,并不断维护更新这两个距离(其实我也不太明白,照着模板敲的,程序运行时间比上一个代码要快一点~~~~~)
代码如下:
#include <cstdio> #include <stack> #include <set> #include <iostream> #include <string> #include <vector> #include <queue> #include <functional> #include <cstring> #include <algorithm> #include <cctype> #include <string> #include <map> #include <iomanip> #include <cmath> #define LL long long #define ULL unsigned long long #define SZ(x) (int)x.size() #define Lowbit(x) ((x) & (-x)) #define MP(a, b) make_pair(a, b) #define MS(arr, num) memset(arr, num, sizeof(arr)) #define PB push_back #define F first #define S second #define ROP freopen("input.txt", "r", stdin); #define MID(a, b) (a + ((b - a) >> 1)) #define LC rt << 1, l, mid #define RC rt << 1|1, mid + 1, r #define LRT rt << 1 #define RRT rt << 1|1 #define BitCount(x) __builtin_popcount(x) #define BitCountll(x) __builtin_popcountll(x) #define LeftPos(x) 32 - __builtin_clz(x) - 1 #define LeftPosll(x) 64 - __builtin_clzll(x) - 1 const double PI = acos(-1.0); const int INF = 0x3f3f3f3f; using namespace std; const int N=5010; const int M=200010; const double eps = 1e-8; const int MAXN = 300 + 10; const int MOD = 1000007; const int dir[][2] = { {-1, 0}, {1, 0}, {0, -1}, {0, 1} }; typedef pair<int, int> pii; int n,m,v[M],u[M],w[M],first ,next[M]; int d1 ,d2 ; bool vis ; void addedge(int a,int b,int c,int i) { u[i]=a; v[i]=b; w[i]=c; next[i]=first[a]; first[a]=i; } void build() { int i,j,a,b,c,t=m<<1; memset(first,-1,sizeof(first)); memset(vis,false,sizeof(vis)); for (i=0;i<t;i+=2){ scanf("%d%d%d",&a,&b,&c); addedge(a,b,c,i); addedge(b,a,c,i+1); } } void dij(int s) { int i,j; priority_queue<pii,vector<pii>,greater<pii> > q; for (i=1;i<=n;d1[i]=d2[i]=INF,i++); d1[s]=0; q.push(make_pair(d1[s],s)); while(!q.empty()) { pii t=q.top(); q.pop(); int val=t.first ,pos=t.second,r; if (d2[pos]<val) continue; //vis[pos]=true; for (i=first[pos];i!=-1;i=next[i]) { r=val+w[i]; if (d1[v[i]]>r){ swap(d1[v[i]],r); q.push(make_pair(d1[v[i]],v[i])); } if (d2[v[i]]>r && d1[v[i]]<r){ d2[v[i]]=r; q.push(make_pair(d2[v[i]],v[i])); } } } } int main() { int i,j; while(~scanf("%d%d",&n,&m)) { build(); dij(1); // for (i=1;i<=n;cout<<d1[i++]<<" "); cout<<endl; cout<<d2 <<endl; } }
相关文章推荐
- POJ 3255 Roadblocks 【次短路】
- poj 3255(次短路)
- POJ3255-Roadblocks-dijkstra求次短路
- poj 3255 次短路问题 Dijkstra 邻接表
- poj 3255(次短路)
- POJ 3255 Roadblocks(次短路)
- Poj 3255 Roadblocks【次短路】【大一最后一题】
- poj-3255-Roadblocks (求到源点的次短路,Dijkstra改进)
- (次短路) poj 3255
- poj 3255 次短路(第k短路) A* + spfa 或 dijkstra
- poj 3255 求次短路路径
- POJ 3255-Roadblocks [次短路 Dijkstra] 《挑战程序设计竞赛》2.5
- POJ 3255 Roadblocks (dijkstra最短路)
- POJ 3255 Roadblocks(A*求次短路)
- Poj 3255(Dijkstra求次短路)
- Light OJ 1099 && poj 3255(次最短路)
- POJ_3255 Roadblocks(最短路)
- POJ-3255-次短路问题
- POJ 3255 Roadblocks (Dijkstra求次短路)
- POJ 3255 Wormholes(最短路最负环)