终于放假了,考试爆炸,算了,还不如学学算法,Dijkstra`s算法。。。
先给题目链接好吧,poj3159Candies:http://poj.org/problem?id=3159
题目意思抄一下:
有N个孩子(N<=3000)分糖果。有M个关系(M<=150000)。每个关系形如:
A B C
表示第B个学生比第A个学生多分到的糖果数目,不能超过C
求第N个学生最多比第1个学生能多分几个糖果 。
这题目交上去还是蛮坑的,开始一直超时,以后有空再问问坤哥。
贴代码吧。
#include<iostream>
#include<queue>
#include<vector>
#include <cstdio>
using namespace std;
int N , M;
struct CNode{
int k , w;//到k点,中间权值为w ;
bool operator <(const CNode &b)const{
return w > b.w; //优先队列重载大于号,保证小的在上;
}
CNode(){};//构造函数,方便直接带入
CNode(int k,int w):k(k),w(w){};
}p , q;
priority_queue<CNode> pq;//优先队列
const int INF = 2e9;//给dis表赋无穷大
vector <int> dis;//dis表,保证单源到其他点的最优权值,这题用不到,但是也可以用
vector <bool> bUsed;// 记录这个点是否已经是最优
vector<vector<CNode> >v;//邻接表
int main() {
scanf("%d%d", & N, & M );//这里最坑。。若果这里用cin>>N>>M;就会超时;
v.clear() , v.resize(N + 1);//3个初始化
dis.clear() , dis.resize(N + 1 , INF);
bUsed.clear() , bUsed.resize(N+1 , false);
for(int i = 1;i <= M;++i){//造图
int re, rs, ci;//A,B,c
scanf("%d%d%d", & re, & rs, & ci);//用cin需要加关闭
v[re].push_back( CNode(rs,ci) );
}
//开始D算法
pq.push( CNode(1,0) );//初始点 1 压入队列,1-1权值为0;
while(!pq.empty()){//若队列为空,则所有和 1 有边的点都排除
p = pq.top() ; pq.pop();//取最上值;
if(bUsed[p.k]) continue;//若果这个点已经求出解,就看下个点;
bUsed[p.k] = true;//第一次见点,保证一个点一次
if(p.k == N) break;//本题只要1-N,所以不用dis,只要到N就行,若果想用表,dis[p.k]=p.w;记录数据
for(int i = 0,j = v[p.k].size(); i < j ; ++i){
q.k = v[p.k][i].k; // p.k所能到的点
if(bUsed[q.k]) continue;//q.k已经求出,跳过
q.w = p.w+v[p.k][i].w;//记录两点权值和;
pq.push(q);//优先队列保证最小在上,即使p到p.k有值,也只会保留最小值,记录bUsed数组,下次见到直接跳;
}
}
cout << p.w;//输出1-N;
return 0;
}
programming is the most fun you can have with your clothes on.