poj 3159 Candies 差分约束
poj 3159 Candies 差分约束
//poj 3159 Candies //差分约束 //不了解差分约束的可以看看这个 //http://hi.baidu.com/qinning199/item/65d270215bb365182a0f1c07 //这题是我的第一题差分约束 //题意: //有n个孩子分糖果,m个孩子的要求,没个要求都有三个数A,B,c //表示A孩子要求B孩子拿到的糖果不能超过自己 c个 //思路: //其实主要就是找出类似最短路中的三角不等式d[v]<=d[u]+w[u,v] //找到这关系后,就可以根据最短路来求解了,求出来的dis数组就是满足每 //个孩子要求的前提下,分配给每个孩子的糖果数 //这题边太多 卡用队列的spfa,用优先队列优化的dijsktra就可以500多ms ac #define comein freopen("in.txt", "r", stdin); #include <stdio.h> #include <string.h> #include <queue> using namespace std; #define INF 1<<30 #define N 30005 struct EDGE { int to, dis, next; }edge[150005]; struct S { int pos, dis; S(int pos, int d) { this->pos = pos; this->dis = d; } S(){} bool operator < (const S &other)const { return this->dis > other.dis; } }; int tot; int head[N], dis[N]; bool vis[N]; void add_edge(int from, int to, int d) { edge[++tot].to = to; edge[tot].dis = d; edge[tot].next = head[from]; head[from] = tot; } void dijsktra(int n_kid) { priority_queue<S> que; dis[1] = 0; int now = 1; while(1) { vis[now] = true; for(int i = head[now]; i != -1; i = edge[i].next) { int to = edge[i].to; if(vis[to] == false && (dis[to] == -1 ||dis[to] - dis[now] > edge[i].dis)) { dis[to] = dis[now] + edge[i].dis; que.push(S(to, dis[to])); } } int tmp = now; while(!que.empty()) { S ttt = que.top(); que.pop(); if(vis[ttt.pos] == false) { now = ttt.pos; break; } } if(tmp == now) break; } } //void spfa(int n_kid) //TLE //{ // queue<int>que; // dis[1] = 0; // que.push(1); // vis[1] = true; // while(!que.empty()) // { // int now = que.front(); // que.pop(); // for(int i = head[now]; i != -1; i = edge[i].next) // { // int to = edge[i].to; // if(dis[to] == -1 || dis[to] - dis[now] >= edge[i].dis) // { // dis[to] = dis[now] + edge[i].dis; // if(vis[to] == false) // { // que.push(to); // vis[to] = true; // } // } // } // vis[now] = false; // } //} int main() { comein int n_kid, m; while(scanf("%d%d", &n_kid, &m) != EOF) { tot = 0; for(int i = 1; i <= n_kid; ++i) { head[i] = -1; vis[i] = false; dis[i] = -1; } for(int i = 0; i < m; ++i) { int from, to, d; //x1孩子 认为 x2 孩子的糖果不能超过自己c个 //x1 - x2 <= c -> dis[to] - dis[from] <= d //那如果 dis[to] - dis[from] >= d的话我们就要维护 //让他保持dis[to] - dis[from] <= d 得到的就是正确的解 scanf("%d%d%d", &from, &to, &d); add_edge(from, to, d); } // spfa(n_kid); //TLE dijsktra(n_kid); printf("%d\n", dis[n_kid]); } return 0; }