1. 程式人生 > >[USACO10FEB]給巧克力Chocolate Giving

[USACO10FEB]給巧克力Chocolate Giving

題意簡敘:

F a r m e r Farmer J

o h n John 有B頭奶牛 ( 1 < = B
< = 25000 ) (1<=B<=25000)
,有 N ( 2
B < = N < = 50000 ) N(2*B<=N<=50000)
個農場,編號 1 N 1-N ,有 M ( N 1 < = M < = 100000 ) M(N-1<=M<=100000) 條雙向邊,第i條邊連線農場 R i R_i S i ( 1 < = R i < = N ; 1 < = S i < = N ) S_i(1<=R_i<=N;1<=S_i<=N) ,該邊的長度是 L i ( 1 < = L i < = 2000 ) L_i(1<=L_i<=2000) 。居住在農場 P i P_i 的奶牛 A ( 1 < = P i < = N ) A(1<=P_i<=N) ,它想送一份新年禮物給居住在農場 Q i ( 1 < = Q i < = N ) Q_i(1<=Q_i<=N) 的奶牛B,但是奶牛A必須先到FJ(居住在編號1的農場)那裡取禮物,然後再送給奶牛B。你的任務是:奶牛A至少需要走多遠的路程?

題目分析:

不難看出,這就是一道單元最短路的裸題

我們可以首先用dijkstra單源最短路跑出1到所有點之間的最短路徑,然後每問一次就呼叫一次即可,具體見程式碼。

程式碼:

#include<cstdio>
#include<queue>
#include<vector>
using namespace std;
#define pa pair<int,int>
#define maxn 100010
priority_queue<pa,vector<pa>,greater<pa> > q;
struct edge
{
    int val,to;
};
int n,m,s,dis[maxn];
bool vis[maxn];
vector<edge>e[maxn]; 
int main()
{
    int b;
    scanf("%d%d%d",&n,&m,&b);
    s=1;
    for(int i=1;i<=m;i++)
    {
        int x,y,z;
        scanf("%d%d%d",&x,&y,&z);
        edge tmp;
        tmp.to=y;
        tmp.val=z;
        e[x].push_back(tmp);
        tmp.to=x;
        tmp.val=z;
        e[y].push_back(tmp);//注意這裡一定要儲存雙向邊
    }
    //start
    for(int i=1;i<=n;i++)
    {
        dis[i]=2147483647;//初始化
    }
    
    dis[s]=0;
    q.push(make_pair(0,s));
    while(q.empty()==0)
    {
        int x=q.top().second;
        q.pop();
        if(vis[x]==1)
        continue;
        vis[x]=1;
        for(int i=0;i<e[x].size();i++)
        {
            int y=e[x][i].to;
            if(dis[x]+e[x][i].val<dis[y])
            {
                dis[y]=dis[x]+e[x][i].val;
                q.push(make_pair(dis[y],y));
            }
        }
    }
    //finish
    //以上的部分皆為dijkstra標準模板,寫的還算比較正規,感謝趣的同志可以收藏一下。(逃
    for(int i=1;i<=b;i++)
    {
		int x,y;
        scanf("%d%d",&x,&y);
        printf("%d\n",dis[x]+dis[y]);//直接呼叫
    }
    return 0;
}