uva 10917 林中漫步 A Walk Through the Forest 迪杰斯特拉

来源:互联网 发布:淘宝评价雷锋侠 编辑:程序博客网 时间:2024/04/28 17:24

林中漫步:

https://uva.onlinejudge.org/external/109/10917.pdf


关键是看懂题目的意思:He considers taking apath from A to B to be progress if thereexists a route from B to his home thatis shorter than any possible route fromA.


如果A能到达B,而且从B回家的路径比所有从A回家的路径都短,只可以选择从A到B(所以总的路径不一定是最短路!!!)



int n,m,S,E;struct  Edge{    int from,to,w;    Edge(){}    Edge(int from,int to,int w):from(from),to(to),w(w){}}  ;vector<Edge>edges;vector<int >G[maxn];struct kk            //dijkstra 队列中的元素{    int x,dis;    bool operator<(const kk a)const    {        return dis>a.dis;    }    kk(){}    kk (int x,int dis):x(x),dis(dis){}};void init(){    edges.clear();    for(int i=1;i<=n;i++)    {        G[i].clear();    }}inline void add_edge(int s,int t ,int w){    edges.push_back(Edge(s,t,w));    edges.push_back(Edge(t,s,w));    int m=edges.size();    G[s].push_back(m-2);    G[t].push_back(m-1);}int d[maxn],done[maxn];void dijkstra(){    memset(done,0,sizeof done);    memset(d,0x3f,sizeof d);    d[E]=0;                    //一开始我从办公室为起点出发,但是与题目的判断条件 (到家的距离)不符    priority_queue< kk >q;    q.push(kk(E,0));    while(!q.empty())    {        kk tmp=q.top();q.pop();        int x=tmp.x;        if(done[x])  continue;        done[x]=1;        for(int i=0;i<G[x].size();i++)        {            int id=G[x][i];            Edge& e=edges[id];            int y=e.to;            if(done[y])   continue;            if(d[y]> d[x]+e.w)            {                d[y]=d[x]+e.w;                q.push(kk(y,d[y]));            }        }    }}int ans;int dp[maxn];int cal(int x)  //记忆化搜索,为什么不是简单的树上搜索,因为一个点可以被多个点到达,这就不是一棵树了。{    if(dp[x]!=-1)  return dp[x];    if(x==E)  return dp[x]=1;    dp[x]=0;    for(int i=0;i<G[x].size();i++)    {        int id=G[x][i];        Edge &e=edges[id];        int y=e.to;        if(d[y]<d[x]) dp[x]+=cal(y);  //判断条件,我曾错过    }     return dp[x];}int main(){    int x,y,z;    S=1,E=2;    while(~scanf("%d",&n)&&n)    {        scanf("%d",&m);        init();        for(int i=1;i<=m;i++)        {            scanf("%d%d%d",&x,&y,&z);            add_edge(x,y,z);        }        dijkstra();        memset(dp,-1,sizeof dp);        printf("%d\n",cal(S) ); //要从办公室(S)开始记忆化搜索,因为从这里开始往d[]小的点走,一定保证路到家(E),反之会走多余的路。    }    return 0;}


#include<cstdio>#include<string>#include<cstring>#include<iostream>#include<cmath>#include<algorithm>#include<climits>#include<queue>#include<vector>#include<map>#include<sstream>#include<set>#include<stack>#include<utility>#pragma comment(linker, "/STACK:102400000,102400000")#define PI 3.1415926535897932384626#define eps 1e-10#define sqr(x) ((x)*(x))#define FOR0(i,n)  for(int i=0 ;i<(n) ;i++)#define FOR1(i,n)  for(int i=1 ;i<=(n) ;i++)#define FORD(i,n)  for(int i=(n) ;i>=0 ;i--)#define  lson   num<<1,le,mid#define rson    num<<1|1,mid+1,ri#define MID   int mid=(le+ri)>>1#define zero(x)((x>0? x:-x)<1e-15)#define mk    make_pair#define _f     first#define _s     secondusing namespace std;const int INF =0x3f3f3f3f;const int maxn= 1000+10   ;//const int maxm=    ;//const int INF=    ;typedef long long ll;const ll inf =1000000000000000;//1e15;//ifstream fin("input.txt");//ofstream fout("output.txt");//fin.close();//fout.close();//freopen("a.in","r",stdin);//freopen("a.out","w",stdout);//by yskysker123




0 0