您的位置:首页 > 其它

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],也即是所求解。

代码如下:

#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;
    }
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: