SDUT 周赛 2493 A Constructing Roads 最短路

http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2493

题意:

给定一个图,给出起点s,终点e 求从起点到终点的最短距离。这里我们允许从其中任意选择一条路径长度减半(这样的处理只能针对一条边)。

思路:

才开始思路是先求出最短路径,然后取最短路径上的路径的最大权值取一半。结果wa致死。。。后来思考才知道思路错了。

这样不能保证最有,可能由起点到终点的一条不在最短路上的路径直接取半就是最优的。 

正确的处理方法是:两遍最短路,分别求出S到所有点的最短路,E到所有点的最短路。然后枚举每条边取半的情况取最小值即可。

#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <cmath>
#include <queue>
#include <stack>
#include <set>
#include <map>
#include <string>

#define CL(a,num) memset((a),(num),sizeof(a))
#define iabs(x)  ((x) > 0 ? (x) : -(x))
#define Min(a,b) (a) > (b)? (b):(a)
#define Max(a,b) (a) > (b)? (a):(b)

#define ll long long
#define inf 0x7f7f7f7f
#define MOD 1073741824
#define lc l,m,rt<<1
#define rc m + 1,r,rt<<1|1
#define pi acos(-1.0)
#define test puts("<------------------->")
#define maxn 100007
#define M 50007
#define N 1007
using namespace std;
//freopen("din.txt","r",stdin);

struct node
{
    int v,w;
    int next;
}g[M*2];
int head[N],ct;

int dis1[N],dis2[N];
int vt[N];
int n,m;

void add(int u,int v,int w)
{
    g[ct].v = v;
    g[ct].w = w;
    g[ct].next = head[u];
    head[u] = ct++;
}

void spfa1(int s)
{
    int i;
    for (i = 1; i <= n; ++i)
    {
        dis1[i] = inf;
        vt[i] = false;
    }
    queue<int>q;
    q.push(s); dis1[s] = 0;
    vt[s] = true;
    while (!q.empty())
    {
        int u = q.front(); q.pop();
        vt[u] = false;
        for (i = head[u]; i != -1; i = g[i].next)
        {
            int v = g[i].v;
            int w = g[i].w;
            if (dis1[v] > dis1[u] + w)
            {
                dis1[v] = dis1[u] + w;
                if (!vt[v])
                {
                    vt[v] = true;
                    q.push(v);
                }
            }
        }
    }
}

void spfa2(int s)
{
    int i;
    for (i = 1; i <= n; ++i)
    {
        dis2[i] = inf;
        vt[i] = false;
    }
    queue<int>q;
    q.push(s); dis2[s] = 0;
    vt[s] = true;
    while (!q.empty())
    {
        int u = q.front(); q.pop();
        vt[u] = false;
        for (i = head[u]; i != -1; i = g[i].next)
        {
            int v = g[i].v;
            int w = g[i].w;
            if (dis2[v] > dis2[u] + w)
            {
                dis2[v] = dis2[u] + w;
                if (!vt[v])
                {
                    vt[v] = true;
                    q.push(v);
                }
            }
        }
    }
}
int main()
{
    //freopen("din.txt","r",stdin);
    int i,j,x,y,w;
    while (~scanf("%d%d",&n,&m))
    {
        CL(head,-1); ct = 0;
        for (i = 0; i < m; ++i)
        {
            scanf("%d%d%d",&x,&y,&w);
            add(x,y,w);
            add(y,x,w);
        }
        int s,e;
        scanf("%d%d",&s,&e);
        spfa1(s);
        if (dis1[e] == inf)
        {
            printf("No solution\n");
            continue;
        }

        spfa2(e);
        int MIN = inf;
        for (i = 1; i <= n; ++i)
        {
            for (j = head[i]; j != -1; j = g[j].next)
            {
                int v = g[j].v;
                int w = g[j].w;
                if (dis1[i] != inf && dis2[v] != inf)
                MIN = min(MIN,dis1[i] + dis2[v] + w/2);
                if (dis2[i] != inf && dis1[v] != inf)
                MIN = min(MIN,dis2[i] + dis1[v] + w/2);
            }
        }
        printf("%d\n",MIN);
    }
    return 0;
}

  

posted @ 2012-12-03 18:01  E_star  阅读(316)  评论(0编辑  收藏  举报