題目鏈接:http://poj.org/problem?id=2394
題目大致含義:
輸入:第一行輸入四個數:f(點數)、p(邊數)、c(牛的頭數)、m(時間限制)
接下來p行每行輸入三個數,分別是起點終點和時間。
接下來的c行按順序輸出每頭牛最終所在的點的位置 。
輸出:先輸出一行表示有多少頭牛有嫌疑,然後按從小到大順序輸出這幾頭牛的編號 。
算法思想:
其實就是穀倉在1號位置,知道在時間m前每頭牛的位置點,現在找出哪隻牛可能到達穀倉。我們用dijkstra算法進行求解:我們可以由題目信息畫出一個圖,先設置源點(穀倉)的distance爲0,然後接下來求出由源點到各點的最小distance,將這些距離存儲在一個dis數組中。若某點的distance小於m,則說明在該點的牛能在時間限制內到到達穀倉,該牛也就有嫌疑。
Fields/distances like this: (poj上的原圖)
6
4------5
| |
2| |
| |
7-----1 |5
9 | |
1| |
| |
2------3
在數據存儲設計中我們使用了vector容器,用於集中存儲某點能到達的點及距離,方便在dijkstra算法中更新distance。使用了dis數組和visit數組(dijkstra算法必不可少的)。使用了queue,方便依次彈出。
代碼:
/*輸入:第一行輸入四個數:f(點數)、p(邊數)、c(牛的頭數)、m(時間限制)
接下來p行每行輸入三個數,分別是起點終點和時間
接下來的c行按順序輸出每頭牛最終所在的點的位置
輸出:先輸出一行表示有多少頭牛有嫌疑,然後按從小到大順序輸出這幾頭牛的編號
*/
#include<iostream>
#include<stdio.h>
#include<limits.h>
#include<queue>
using namespace std;
struct Edge{
int v2 ;
int cost;
};
vector<Edge>graph[501]; //題目限制f的範圍在1-500
bool visit[501]={false};
int dis[501];
int f,p,c,m;
queue<int>q;
void dijkstra(){
int ii=0;
for(ii=0;ii<f;ii++){ //我們最終要把每個點上的dis求出來,所以要進行f次循環,每次循環的任務就是求出此次要確定的某點以及利用該點去更新周邊點的dis
int v=0;
int min_v=INT_MAX;
for(int j=1;j<=f;j++){
if(!visit[j] && dis[j]<min_v){
v = j;
min_v = dis[j];
}
}
visit[v] = true; //確定點v已經是這次挑出來的到源點最小的點了,然後我們要利用該點再去更新v周邊的點的dis
//cout<<"v="<<v<<" ";
for(int i=0;i<graph[v].size();i++){
int temp = graph[v][i].v2;
// cout<<temp<<" "<<visit[temp]<<" "<<dis[v]+graph[v][i].cost<<" ";
if(!visit[temp] && dis[v]+graph[v][i].cost<dis[temp]){
dis[temp] = dis[v]+graph[v][i].cost;
}
}
}
}
int main(){
cin>>f>>p>>c>>m;
int i;
int a,b,c1;
for(i=0;i<p;i++){
cin>>a>>b>>c1;
graph[a].push_back({b,c1});
graph[b].push_back({a,c1});
}
fill(dis+1,dis+1+f,INT_MAX); //令圖上所有點最初大小爲無窮大
dis[1]=0; //設置源點的距離爲0
dijkstra();
int vv;
for(i=1;i<=c;i++){
cin>>vv;
//cout<<dis[vv]<<" ";
if(dis[vv]<=m)
q.push(i);
}
cout<<q.size()<<endl;
while(!q.empty()){
int ww = q.front();
q.pop();
cout<<ww<<endl;
}
}