POJ3268 解题报告

来源:互联网 发布:sql server 2008 出错 编辑:程序博客网 时间:2024/06/06 01:28
Silver Cow Party
Time Limit: 2000MSMemory Limit: 65536KTotal Submissions: 22601Accepted: 10344

Description

One cow from each of N farms (1 ≤N ≤ 1000) conveniently numbered 1..N is going to attend the big cow party to be held at farm #X (1 ≤ XN). A total ofM (1 ≤M ≤ 100,000) unidirectional (one-way roads connects pairs of farms; roadi requiresTi (1 ≤Ti ≤ 100) units of time to traverse.

Each cow must walk to the party and, when the party is over, return to her farm. Each cow is lazy and thus picks an optimal route with the shortest time. A cow's return route might be different from her original route to the party since roads are one-way.

Of all the cows, what is the longest amount of time a cow must spend walking to the party and back?

Input

Line 1: Three space-separated integers, respectively:N,M, andX
Lines 2..
M+1: Linei+1 describes roadi with three space-separated integers:Ai,Bi, andTi. The described road runs from farmAi to farmBi, requiringTi time units to traverse.

Output

Line 1: One integer: the maximum of time any one cow must walk.

Sample Input

4 8 21 2 41 3 21 4 72 1 12 3 53 1 23 4 44 2 3

Sample Output

10

Hint

Cow 4 proceeds directly to the party (3 units) and returns via farms 1 and 3 (7 units), for a total of 10 time units.

Source

USACO 2007 February Silver


这是一题求解最短路的题目
先发TLE代码,AC代码在最下面
刚拿到这一题的时候,我想到的是用floyd算法,因为这一题要求从i到j的距离,也要求从j到i的距离,而这里面的路线有都是单向的,所以我就想到了这个求解任意两点之间最短路的算法,但是我看了一下数据,一共有1000个节点,而这一算法的时间复杂度为O(|v|^3),这样算下来的话就是1,000,000,000了,十位数,显然是太大了,但是我想偷懒啊,不想去想其他办法了,所以我就打算冒险试一下,反正也不是比赛,于是我就胡乱搞了一通,为了减少时间我还特意用了scanf和printf,但是结果还是TLE了,也算是预料之中了吧
下面这是TLE的代码
#include<cstdio>#include<algorithm>#include<iostream>#include<cstring>using namespace std;const int INF=0x3f3f3f3f;const int maxn=1000+100;const int maxm=100000+100;int d[maxn][maxn];int N,M,X;void warshall();void solve();void show();int main(){    while(scanf("%d%d%d",&N,&M,&X)==3)    {        memset(d,0x3f,sizeof(d));        for(int i=0;i<=N;i++)            d[i][i]=0;        for(int i=0;i<M;i++)        {            int a,b,t;            scanf("%d%d%d",&a,&b,&t);            d[a][b]=t;        }        warshall();        solve();        //show();    }    return 0;}void warshall(){    for(int k=1;k<=N;k++)        for(int i=1;i<=N;i++)            for(int j=1;j<=N;j++)                d[i][j]=min(d[i][j],d[i][k]+d[k][j]);}void solve(){    int ans=0;    for(int i=1;i<=N;i++)        if(i!=X)            ans=max(ans,d[i][X]+d[X][i]);    printf("%d\n",ans);}void show(){    for(int i=1;i<=N;i++)    {        for(int j=1;j<=N;j++)            if(d[i][j]==INF) printf("%4s","inf");            else printf("%4d",d[i][j]);        printf("\n");    }}

TLE了之后我就开始想其他办法了,Floyd不能用,那么自然我就只剩下bellman和dijkstra能用了,因为我只会这几招了
如果不对这两个算法进行优化,那么他们的时间复杂度都是O(ElogV),算一下是九位数,比之前这个少一位数,但是这样还是太悬了,如果能降低到七位数或以下那肯定是不会TLE的,所以自然还是要优化一下,但是bellman的我不会优化版的,所以最终选了dijkstra算法
但是使用dijkstra算法的话需要使用两次,一次正着用一次反着用。也就是说,第一次使用的时候,我们的路的方向都是正确的,和输入的方向都一样,这一次使用算出来的是X点到各个点的最短路;但是第二次使用的时候,我们将所有的路的方向反过来了,这样的话我们得到的就是各个点到X点的最短路了
#include<iostream>#include<algorithm>#include<vector>#include<queue>#include<cstdio>using namespace std;struct edge{    int to;    int cost;};typedef pair<int,int> P;const int INF=2e9;const int maxn=1000+10;const int maxm=100000+100;vector<edge> G1[maxn],G2[maxn];int d1[maxn],d2[maxn];int N,M,X;void dijkstra1(int s);void dijkstra2(int s);void solve();void show();int main(){    while(cin>>N>>M>>X)    {        for(int i=0;i<=N;i++)        {            G1[i].clear();            G2[i].clear();        }        for(int i=0;i<M;i++)        {            int a,b,t;            edge e1,e2;            cin>>a>>b>>t;            e1.to=b; e2.to=a; e1.cost=e2.cost=t;            G1[a].push_back(e1);            G2[b].push_back(e2);        }        dijkstra1(X);        dijkstra2(X);        solve();        //show();    }    return 0;}void dijkstra1(int s){    fill(d1,d1+maxn,INF);    d1[s]=0;    priority_queue<P,vector<P>,greater<P>> que;    que.push(P(0,s));    while(!que.empty())    {        P p=que.top(); que.pop();        int v=p.second;        if(d1[v]<p.first) continue;        for(int i=0;i<G1[v].size();i++)        {            edge e=G1[v][i];            if(d1[e.to]>d1[v]+e.cost)            {                d1[e.to]=d1[v]+e.cost;                que.push(P(d1[e.to],e.to));            }        }    }}void dijkstra2(int s){    fill(d2,d2+maxn,INF);    d2[s]=0;    priority_queue<P,vector<P>,greater<P>> que;    que.push(P(0,s));    while(!que.empty())    {        P p=que.top(); que.pop();        int v=p.second;        if(d2[v]<p.first) continue;        for(int i=0;i<G2[v].size();i++)        {            edge e=G2[v][i];            if(d2[e.to]>d2[v]+e.cost)            {                d2[e.to]=d2[v]+e.cost;                que.push(P(d2[e.to],e.to));            }        }    }}void solve(){    int ans=0;    for(int i=1;i<=N;i++)            ans=max(ans,d1[i]+d2[i]);    cout<<ans<<endl;}void show(){    for(int i=1;i<=N;i++)        cout<<d1[i]<<" ";    cout<<endl;    for(int i=1;i<=N;i++)        cout<<d2[i]<<" ";    cout<<endl;}