pku 3159 Candies

狗题~~

做到我快抓狂,很明显一道差分约束题

因为没写过bellman,所以刚开始的时候用bellman写,超时。。理解

后来用spfa+queue ~~~还是超时了

后来看了discuss~~才知道别人用spfa+queue都是超时的,然后用spfa+stack才不超时。

然后我改成spfa+stack,一交,,,还是超时~~郁闷~~后来再详细看看discuss,估计数据是加强过,以前可以过的现在未必可以过

然后有人提出跟高效一点的办法,,,dijkstra+优先级队列,,,看到别人写了ac了, 自己也写stl写一个,。。无论怎么交都是tle  >_<

然后听说spfa+stack是可以过的,但是卡stl ,。绝望之际好像看到了新生,于是改用一个自己写的stack+vector的spfa。。。提交~依然tle~~~~

 

崩溃中~~这时候听一个师兄说他用了自己用链表实现的邻接表还有自己写的栈来写spfa,500MS ac了,,于是百般无奈下自己也这样做~~

终于以1450MS低空飞过。。真不知道为什么同样的实现别人的是500MS而自己的1450MS???郁闷中

 

超时代码:

 

// 用到stl的vector版本,超时 #include <cstdio> #include <vector> #define N 30001 #define INF 100000000 using namespace std; struct node { int id; int w; node(){} node(int id, int w):id(id), w(w){} }; int sta[N]; int tp; vector<node> g[N]; int dis[N]; void spfa(int n, int s) { int tp = 0; int visit[N] = {0}; node nd; for(int i = 0; i <= n; ++i) { dis[i] = INF; } dis[s] = 0; visit[s] = 1; sta[tp++] = s; while(tp) { int u = sta[tp-1]; –tp; visit[u] = 0; for(int i = 0; i < g[u].size(); ++i) { int v = g[u][i].id; int w = g[u][i].w; if(dis[v] > dis[u] + w) { //printf(“dis[%d]:%d > dis[%d]:%d + %d/n”, v, dis[v], u, dis[u], w); dis[v] = dis[u] + w; if(!visit[v]) { sta[tp++] = v; visit[v] = 1; } } } } } int main () { int n,m; int u,v,d; scanf(“%d%d”, &n, &m); for(int i = 0; i < m; ++i) { scanf(“%d%d%d”, &u ,&v, &d); g[u].push_back(node(v, d)); } spfa(n, 1); printf(“%d/n”, dis[n]); return 0; }

// 优先级队列+dijkstra版本,,,超时 #include <cstdio> #include <vector> #include <queue> #define N 30001 #define INF 100000000 using namespace std; struct node { int id; int w; node(int id, int w):id(id), w(w){} bool operator<(const node &r) const { return w > r.w; } }; vector<node> g[N]; int dis[N]; int dijkstra(int n, int s, int e) { priority_queue<node> que; bool visit[N] = {false}; int u, v, w, tmp, sz; node fr(0, 0); for(int i = 0; i <= n; ++i) { dis[i] = INF; } dis[s] = 0; que.push(node(s, 0)); while(!que.empty()) { fr = que.top(); que.pop(); u = fr.id; if(visit[u]) continue; // 如果某个点已经是黑色了,就不用再处理了 if(u == e) return dis[e]; // 早到终点直接返回 visit[u] = true; // 染成黑色 sz = g[u].size(); for(int i = 0; i <sz; ++i) { // 对u相邻的点进行松弛 v = g[u][i].id; w = g[u][i].w; if(!visit[v] && dis[v] > (tmp = dis[u] + w)) { dis[fr.id = v] = fr.w = tmp; que.push(fr); } } } return dis[e]; } int main () { int n,m; int u,v,d; scanf(“%d%d”, &n, &m); for(int i = 0; i < m; ++i) { scanf(“%d%d%d”, &u ,&v, &d); g[u].push_back(node(v, d)); } dijkstra(n, 1, n); printf(“%d/n”, dis[n]); return 0; }

AC 代码:

 

 

#include <cstdio> #define N 30002 #define INF 100000000 typedef struct node{ int id; int w; struct node *next; }node; node table[N]; int sta[N+10]; int tp; int dis[N]; void spfa(int n, int s) { int tp = 0; bool visit[N] = {false}; int u,v,w; node *p; for(int i = 0; i <= n; ++i) { dis[i] = INF; } dis[s] = 0; visit[s] = true; sta[tp++] = s; while(tp) { u = sta[tp-1]; –tp; visit[u] = 0; for(p = table[u].next; p; p = p->next) { v = p->id; w = p->w; if(dis[v] > dis[u] + w) { //printf(“dis[%d]:%d > dis[%d]:%d + %d/n”, v, dis[v], u, dis[u], w); dis[v] = dis[u] + w; if(!visit[v]) { sta[tp++] = v; visit[v] = true; } } } } } void add(int u, int v, int d) { node *p = table[u].next; node *newnode = new node; newnode->next = p; newnode->id = v; newnode->w = d; table[u].next = newnode; } int main () { int n,m; int u,v,d; node nd; scanf(“%d%d”, &n, &m); for(int i = 1; i <= n; ++i) { table[i].next = NULL; table[i].id = i; table[i].w = 0; } for(int i = 0; i < m; ++i) { scanf(“%d%d%d”, &u ,&v, &d); add(u,v,d); } //show(n); spfa(n, 1); printf(“%d/n”, dis[n]); return 0; }

终于知道为什么这么慢了

原来用new开内存会很慢的,把我们链表要用到的节点一次性够就可以快很多了

原来1450MS, 一改之后500MS就可以了

#include <cstdio> #include <cstring> #define N 30001 #define EMAX 150000 typedef struct node{ int id; int w; struct node *next; }node; node linknode[EMAX]; // 在这里一次性开够我们要用的内存比运行时用new开辟可以快3倍 int used; node table[N]; int sta[N+10]; int tp; int dis[N]; void spfa(int n, int s) { int tp = 0; bool visit[N] = {false}; int u,v,w; node *p; memset(dis, ‘~’, sizeof(dis)); dis[s] = 0; visit[s] = true; sta[tp++] = s; while(tp) { u = sta[tp-1]; –tp; visit[u] = 0; for(p = table[u].next; p; p = p->next) { v = p->id; w = p->w; if(dis[v] > dis[u] + w) { //printf(“dis[%d]:%d > dis[%d]:%d + %d/n”, v, dis[v], u, dis[u], w); dis[v] = dis[u] + w; if(!visit[v]) { sta[tp++] = v; visit[v] = true; } } } } } void add(int u, int v, int d) { node *p = table[u].next; node *newnode = &linknode[used++]; newnode->next = p; newnode->id = v; newnode->w = d; table[u].next = newnode; } int main () { int n,m; int u,v,d; node nd; scanf(“%d%d”, &n, &m); for(int i = 1; i <= n; ++i) { table[i].next = NULL; table[i].id = i; table[i].w = 0; } for(int i = 0; i < m; ++i) { scanf(“%d%d%d”, &u ,&v, &d); add(u,v,d); } spfa(n, 1); printf(“%d/n”, dis[n]); return 0; }

点赞