poj1062(Dijkstra)
阿新 • • 發佈:2018-11-29
這題用到了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;
}