SDUT 周赛 2498 AOE网上的关键路径
http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2498
题意:汉语...
思路:
比赛的时候是按spfa正向的处理的,然后记录每一点的前一个点如果出现相等去最小的那个。结果wa。赛后才知道这样处理时错的。
比如下图:如果现在终点是6,现在2和3都能使6的距离达到最大且值相同。我们处理的时候会选2,但还是2这条路径却不是最优的,反而3是最有的。
所以我们逆向见图,求一个最短路然后倒着输出就好了。
#include <iostream> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm> #include <cmath> #include <queue> #include <stack> #include <set> #include <map> #include <string> #define CL(a,num) memset((a),(num),sizeof(a)) #define iabs(x) ((x) > 0 ? (x) : -(x)) #define Min(a,b) (a) > (b)? (b):(a) #define Max(a,b) (a) > (b)? (a):(b) #define ll long long #define inf 0x7f7f7f7f #define MOD 1073741824 #define lc l,m,rt<<1 #define rc m + 1,r,rt<<1|1 #define pi acos(-1.0) #define test puts("<------------------->") #define maxn 100007 #define M 50007 #define N 10007 using namespace std; //freopen("din.txt","r",stdin); struct node { int v,w; int next; }g[M]; int head[N],ct; struct mm { int x,y; }p[M]; int pre[N]; int vt[N]; int dis[N]; int id[N],cd[N]; int n; void add(int u,int v,int w) { g[ct].v = v; g[ct].w = w; g[ct].next = head[u]; head[u] = ct++; } void spfa(int s) { int i,j; for (i = 1; i <= n; ++i) { dis[i] = -inf; vt[i] = false; pre[i] = -1; } queue<int>q; q.push(s); dis[s] = 0; vt[s] = true; while (!q.empty()) { int u = q.front(); q.pop(); for (i = head[u]; i != -1; i = g[i].next) { int v = g[i].v; int w = g[i].w; if (dis[v] < dis[u] + w) { pre[v] = u; dis[v] = dis[u] + w; if (!vt[v]) { vt[v] = true; q.push(v); } } else if (dis[v] == dis[u] + w && pre[v] != -1 && pre[v] > u) { pre[v] = u; if (!vt[v]) { vt[v] = true; q.push(v); } } } vt[u] = false; } } int main() { //freopen("din.txt","r",stdin); int m; int i; int u,v,w; while (~scanf("%d%d",&n,&m)) { CL(head,-1); ct = 0; CL(id,0); CL(cd,0); for (i = 0; i < m; ++i) { scanf("%d%d%d",&u,&v,&w); add(v,u,w); id[u]++; cd[v]++; } int s,e; for (i = 1; i <= n; ++i) { if (id[i] == 0) s = i; if (cd[i] == 0) e = i; } // printf("%d %d\n",s,e); spfa(s); printf("%d\n",dis[e]); int x = e; int len = 0; while (x != s) { printf("%d %d\n",x,pre[x]); len++; x = pre[x]; } } return 0; }