zoukankan      html  css  js  c++  java
  • poj

    http://poj.org/problem?id=3268

    每头牛都要去标号为X的农场参加一个party,农场总共有N个(标号为1-n),总共有M单向路联通,每头牛参加完party之后需要返回自己的农场,但是他们都想选一条最近的路,并且由于路是单向的,去的路和来的路选择可能不一样,问来去时间之和最大是多少?

    这题等于给定了起点和终点,那么求出(d[x][i]+d[i][x])最大的那个即可。

    开始错了几次,太不小心了,就是最后求最大值的时候,用了一个临时变量没置0,所以可能会导致错误。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <queue>
     7 #include <set>
     8 #include <map>
     9 #include <string>
    10 #include <cmath>
    11 #include <cstdlib>
    12 #include <ctime>
    13 using namespace std;
    14 const int maxn= 1010;
    15 const int INF = 1<<29;
    16 struct edge{
    17     int to,cost;
    18     edge(){}
    19     edge(int x,int y) {
    20         to=x;
    21         cost=y;
    22     }
    23 };
    24 typedef pair<int,int>P;
    25 
    26 int N,M,X;
    27 vector<edge>G[maxn];
    28 int d[maxn];
    29 
    30 int dijkstra(int s,int t) {
    31     priority_queue<P,vector<P>,greater<P> >que;
    32     for(int i=0;i<=N;i++) d[i]=INF;
    33     d[s]=0;
    34     que.push(P(0,s));
    35 
    36     while(!que.empty()) {
    37         P p=que.top(); que.pop();
    38         int v=p.second;
    39         if(v==t) return d[t];
    40         if(d[v]<p.first) continue;
    41         for(int i=0;i<G[v].size();i++) {
    42             edge e=G[v][i];
    43             if(d[e.to]>d[v]+e.cost) {
    44                 d[e.to]=d[v]+e.cost;
    45                 que.push(P(d[e.to],e.to));
    46             }
    47         }
    48     }
    49 }
    50 
    51 int main()
    52 {
    53     //freopen("a.txt","r",stdin);
    54     //freopen("b.txt","w",stdout);
    55     int a,b,c;
    56     while(~scanf("%d%d%d",&N,&M,&X)) {
    57         for(int i=0;i<M;i++) {
    58             scanf("%d%d%d",&a,&b,&c);
    59             G[a].push_back(edge(b,c));
    60         }
    61         int sum=0;
    62         for(int i=1;i<=N;i++) {
    63             sum=max(sum,dijkstra(i,X)+dijkstra(X,i));
    64         }
    65         printf("%d
    ",sum);
    66     }
    67     return 0;
    68 }

     还有一种方法,首先求出点X到各个点i的最短路径,这就是奶牛返回的最短距离,然后把路径反向,在求点X到各个点i的最短距离,就是每个点到点X的最短距离。

     最后把两个距离相交即可。

     不过对于反向,不是很明白。

     时间直接从600多ms降到60多ms。

     1 #include <cstdio>
     2 #include <cstring>
     3 #include <iostream>
     4 #include <algorithm>
     5 #include <vector>
     6 #include <queue>
     7 #include <set>
     8 #include <map>
     9 #include <string>
    10 #include <cmath>
    11 #include <cstdlib>
    12 #include <ctime>
    13 using namespace std;
    14 const int maxn= 1010;
    15 const int INF = 1<<29;
    16 struct edge{
    17     int to,cost;
    18     edge(){}
    19     edge(int x,int y) {
    20         to=x;
    21         cost=y;
    22     }
    23 };
    24 typedef pair<int,int>P;
    25 
    26 int N,M,X;
    27 vector<edge>G[maxn],RG[maxn];
    28 int d[maxn],rd[maxn];
    29 
    30 void dijkstra(int s) {
    31     priority_queue<P,vector<P>,greater<P> >que;
    32     for(int i=0;i<=N;i++) d[i]=INF;
    33     d[s]=0;
    34     que.push(P(0,s));
    35 
    36     while(!que.empty()) {
    37         P p=que.top(); que.pop();
    38         int v=p.second;
    39         if(d[v]<p.first) continue;
    40         for(int i=0;i<G[v].size();i++) {
    41             edge e=G[v][i];
    42             if(d[e.to]>d[v]+e.cost) {
    43                 d[e.to]=d[v]+e.cost;
    44                 que.push(P(d[e.to],e.to));
    45             }
    46         }
    47     }
    48 }
    49 
    50 int main()
    51 {
    52     //freopen("a.txt","r",stdin);
    53     //freopen("b.txt","w",stdout);
    54     int a,b,c;
    55     scanf("%d%d%d",&N,&M,&X);
    56         for(int i=0;i<M;i++) {
    57             scanf("%d%d%d",&a,&b,&c);
    58             G[a].push_back(edge(b,c));
    59             RG[b].push_back(edge(a,c)); //存储 反向边
    60         }
    61         dijkstra(X);   //第一次 dijkstra 是求X到各个点的距离
    62         //for(int i=1;i<=N;i++) printf("%d
    ",d[i]);
    63         for(int i=1;i<=N;i++) G[i]=RG[i];  //然后  把反向存储的边赋值给 G
    64       //  for(int i=1;i<=N;i++) {
    65           //  for(int j=0;j<G[i].size();j++)
    66               //  cout<<G[i][j].to<<" "<<G[i][j].cost<<endl;
    67        //}
    68         memcpy(rd,d,sizeof(d));  //把第一次的 最短距离  保存
    69 
    70         dijkstra(X);  //反向的 dijkstra 求出每个点到X的最短距离
    71         //for(int i=1;i<=N;i++) printf("%d
    ",d[i]);
    72         int sum=0;   //枚举最大和 
    73         for(int i=1;i<=N;i++) {
    74             sum=max(sum,d[i]+rd[i]);
    75         }
    76         printf("%d
    ",sum);
    77     return 0;
    78 }
  • 相关阅读:
    屏蔽Alt+Enter、Ctrl+Alt+Del、Ctrl+Esc等功能键(Windows 98/Me)
    获取本月第一天和最后一天的最简单的写法
    PHP程序员的优化调试技术和技巧
    Windows关机函数ExitWindowsEx使用大全(适用Windows所有操作平台)
    屏蔽Alt+Enter、Ctrl+Alt+Del、Ctrl+Esc等功能键(Windows 98/Me)
    PHP程序员的优化调试技术和技巧
    Ajax,再生还是幻灭好文推荐
    RAID 分类
    Ajax,再生还是幻灭好文推荐
    Windows关机函数ExitWindowsEx使用大全(适用Windows所有操作平台)
  • 原文地址:https://www.cnblogs.com/nowandforever/p/4503364.html
Copyright © 2011-2022 走看看