1. 程式人生 > >poj1062(Dijkstra)

poj1062(Dijkstra)

這題用到了Dijkstra演算法,難點在處理等級限制。我天真以為把前驅節點和當前訪問節點比較一下就行了。too young too naive…這個需要列舉所有等級範圍。
因為酋長是必須要訪問的節點,所以要以酋長為中心列舉。比如說酋長等級是3,等級限制是4。符合條件的範圍是-1—3、0—4、1—5、2—6、3—7(會有比酋長等級高的人)。所以需要搜尋5次,把不符合條件的節點標記為不能訪問。
比如果下面這組資料

4 5
800 3 2
2 1
3 2
20 1 1
4 1
30 5 1
4 2
100 4 1
5 0
5 7 0

根據資料建圖
在這裡插入圖片描述

最優路徑為:1->3->4->5 結果為 2+2+0+5=9。不能走1->2->4->5,因為頂點2的等級為1,頂點5的等級為7,等級差距大於4。
貼程式碼

//Memory 224k Time 47ms
#include<iostream>
#include<queue>
#include<vector>
using namespace std;
int M,N;
class road
{
public:
	int end;       //通向的節點
	int weight;    //路徑的長度
};

class node
{
public:
	int value;       //價值
	int level;       //等級
}node[105];

class Graph
{
public:
	int v;           //頂點個數
int mark[105]; //標記 vector<road> *adj; //鄰接表 Graph(int n); ~Graph(); void addEdge(int b,int e,int w); }; Graph::Graph(int n) { v=n; adj=new vector<road>[n]; } Graph::~Graph() { delete []adj; } void Graph::addEdge(int b,int e,int w) { road r; r.end=e; r.weight=w; adj[b].push_back
(r); } class Dist { public: int index; //頂點號 int length; //長度 friend bool operator<(const Dist &a,const Dist &b) { return a.length>b.length; } }; int Dijkstra(Graph & g,int s) { Dist *D = new Dist[g.v]; for(int i=1;i<g.v;i++) { D[i].index = i; D[i].length=1<<30; } D[s].length=0; priority_queue<Dist> aqueue; aqueue.push(D[s]); for(int i=1;i<g.v;i++) { Dist d; bool FOUND=false; while(!aqueue.empty()) { d=aqueue.top(); aqueue.pop(); if(g.mark[d.index]==0) { FOUND=true; break; } } if(!FOUND) break; int now_node = d.index; g.mark[now_node]=1; vector<road>::iterator ii = g.adj[now_node].begin(); for(;ii!=g.adj[now_node].end();ii++) { if( g.mark[ii->end]==0 && D[ii->end].length > D[now_node].length + ii->weight) { D[ii->end].length = D[now_node].length + ii->weight; aqueue.push(D[ii->end]); } } } int *ans=new int[g.v]; for(int i=1;i<g.v;i++) { ans[i]=D[i].length+node[i].value; } int min=1<<30; for(int i=1;i<g.v;i++) { if(ans[i]<min) { min=ans[i]; } } return min; } int main() { int P,L,X; int T,V; cin>>M>>N; Graph g(N+1); for(int i=1;i<=N;i++) { cin>>P>>L>>X; node[i].value=P; node[i].level=L; for(int j=1;j<=X;j++) { cin>>T>>V; g.addEdge(i,T,V); } } int ans=1<<30; for(int i=node[1].level - M; i<=node[1].level; i++) //等級篩選 { memset(g.mark,0,sizeof(g.mark)); for(int j=1;j<g.v;j++) { if(node[j].level<i || node[j].level>i+M) //不符合條件 { g.mark[j]=1; //標記 } } ans=min(Dijkstra(g,1),ans); //搜尋 } cout<<ans<<endl; return 0; }