http://acm.sdut.edu.cn/sdutoj/problem.php?action=showproblem&problemid=2498
题意:给定 一个 有向图 ,求出 从 图中只有 一个 入度为0 的点 s 和 一个 出度 为0 的 点 t 求 s 到t的 最长路径 若有 多条 输出 字典序最小的!
题解:
SPFA + 反向建图 。
对于 所要求的路径 ,s 的下一个点 是 与 s相连 且 距离 t 最长的点 ,若有 多个 选择序号 最小的 。
所以 自然 想到 求 各个点 到 t 的 最短距离 ,这样就 用到了 反向建图,并用 pre 记录的他的 前驱结点
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<iostream> 5 #include<algorithm> 6 #include<set> 7 #include<map> 8 #include<queue> 9 #include<vector> 10 #include<string> 11 #define inf 99999999 12 #define maxn 15000 13 #define CL(a,b) memset(a,b,sizeof(a)) 14 #define ll long long 15 //#define mx 1000010 16 using namespace std; 17 int n, m ,s,t; 18 int in[maxn],out[maxn] ; 19 struct node 20 { 21 int u ; 22 int v; 23 int w; 24 int next; 25 }p[maxn*4] ; 26 int cnt ; 27 int head[maxn] ; 28 void add(int u,int v,int w) 29 { 30 p[cnt].u = u; 31 p[cnt].v= v; 32 p[cnt].w = w ; 33 p[cnt].next = head[u] ; 34 head[u] = cnt++ ; 35 36 } 37 queue<int>que; 38 int dis[maxn],pre[maxn] ; 39 int a[maxn] ; 40 int vis[maxn] ; 41 void solve() 42 { 43 int i ; 44 for(i = 0; i <= n;i++) 45 { 46 dis[i] = -inf ; 47 pre[i] = inf ; 48 } 49 while(!que.empty())que.pop() ; 50 51 CL(vis, 0) ; 52 53 dis[s] = 0 ; 54 que.push(s) ; 55 vis[s] = 1 ; 56 while(!que.empty()) 57 { 58 int u = que.front() ;que.pop() ; 59 vis[u] = 0 ; 60 for(i = head[u] ; i != -1;i = p[i].next) 61 { 62 int v = p[i].v ; 63 int w = p[i].w ; 64 65 if(dis[u] + w >= dis[v]) 66 { 67 if(dis[u] + w > dis[v]) 68 { 69 dis[v] = dis[u] + w; 70 pre[v] = u ; 71 72 if(!vis[v]) 73 que.push(v) ; 74 } 75 if(dis[u] + w == dis[v]) 76 { 77 if(u < pre[v]) 78 { 79 pre[v] = u ; 80 if(!vis[v]) 81 que.push(v) ; 82 } 83 } 84 85 } 86 87 } 88 } 89 90 91 int num = 0; 92 int tmp = t ; 93 while(tmp != s) 94 { 95 a[num++] = tmp; 96 tmp= pre[tmp] ; 97 } 98 a[num] = s; 99 100 printf("%d\n",dis[t]) ; 101 for(i = 0 ; i< num;i++) 102 { 103 printf("%d %d\n",a[i],a[i + 1]) ; 104 } 105 106 107 108 } 109 int main() 110 { 111 int i ,x,y,d ; 112 while(scanf("%d%d",&n,&m)!=EOF) 113 { 114 cnt = 0 ; 115 CL(head, -1) ; 116 117 for(i = 0 ; i<= n;i++) 118 { 119 out[i] = in[i] = 0 ; 120 } 121 for(i =0 ; i < m;i++) 122 { 123 scanf("%d%d%d",&x,&y,&d); 124 out[y]++; 125 in[x] ++ ; 126 add(y,x,d) ; 127 128 } 129 for(i = 1; i <= n;i++) 130 { 131 if(in[i] == 0) 132 s = i; 133 134 if(out[i] == 0) 135 t = i ; 136 } 137 solve() ; 138 139 140 } 141 }