SGU 515 Dij+Topsort
题目大意:给定N个点M条边的无向图,以及一些必经过的点,求输出长度最短路径。
题目分析:想办法把图转化成DAG,于是找出最远点建立最短路树,跑topsort
1 #include<bits/stdc++.h> 2 #define maxn 100010 3 #define LL long long 4 #define Pii pair<LL,int> 5 #define pb push_back 6 #define mp make_pair 7 #define fi first 8 #define se second 9 const LL INF = 0x7fffffff; 10 using namespace std; 11 LL d[maxn], mi = -1; 12 struct Node{ 13 int u,v; 14 LL cost; 15 }e[maxn]; 16 int n, m, dir, ddir, cnt = 0, dp[maxn]; 17 LL cc[maxn]; 18 bool cover[maxn]; 19 int seg[maxn], k; 20 vector<Pii> G[maxn]; 21 vector<pair<LL, pair<int,int> > > T[maxn]; 22 int in[maxn]; 23 int pre[maxn]; 24 int path[maxn], num = 0; 25 void find(int x){ 26 if(x == dir) return; 27 int current_path = pre[x]; 28 if(e[current_path].u == x) 29 find(e[current_path].v); 30 else 31 find(e[current_path].u); 32 path[++ num] = current_path; 33 } 34 void Dij(int fa){ 35 bool vis[maxn]; 36 memset(vis, false, sizeof(vis)); 37 for(int i = 1; i <= n; i ++){ 38 d[i] = INF; 39 } 40 d[fa] = 0; 41 priority_queue<Pii,vector<Pii>, greater<Pii> > Q; 42 Q.push(mp(d[fa], fa)); 43 Pii p, cur; 44 int pos, now; 45 while(!Q.empty()){ 46 p = Q.top(); 47 pos = p.se; 48 Q.pop(); 49 if(vis[pos]) continue; 50 vis[pos] = true; 51 for(int i = 0; i < G[pos].size(); i ++){ 52 cur = G[pos][i]; 53 if(!vis[cur.se] && d[cur.se] > d[pos] + cur.fi){ 54 d[cur.se] = d[pos] + cur.fi; 55 Q.push(mp(d[cur.se], cur.se)); 56 } 57 } 58 } 59 } 60 int main(){ 61 int a, b, t; 62 cin >> n >> m; 63 for(int i = 1; i <= m; i ++){ 64 cin >> a >> b >> t; 65 if(a == b){ 66 m --; 67 i --; 68 continue; 69 } 70 e[++ cnt].u = a, e[cnt].v = b, e[cnt].cost = t; 71 G[a].pb(mp(t, b)); 72 G[b].pb(mp(t, a)); 73 } 74 cin >> k; 75 for(int i = 1; i <= k; i ++){ 76 cin >> seg[i]; 77 cover[seg[i]] = true; 78 } 79 Dij(seg[1]); 80 for(int i = 1; i <= n; i ++){ 81 if(cover[i] && d[i] > mi){ 82 mi = d[i]; 83 dir = i; 84 } 85 } 86 Dij(dir); 87 for(int i = 1; i <= cnt; i ++){ 88 if(e[i].u == e[i].v) continue; 89 if(d[e[i].u] == d[e[i].v] + e[i].cost){ 90 T[e[i].v].pb(mp(e[i].cost, mp(e[i].u, i))); 91 in[e[i].u] ++; 92 } 93 else if(d[e[i].v] == d[e[i].u] + e[i].cost){ 94 T[e[i].u].pb(mp(e[i].cost, mp(e[i].v, i))); 95 in[e[i].v] ++; 96 } 97 } 98 queue<int> Q; 99 for(int i = 1; i <= n; i ++){ 100 dp[i] = (cover[i] ? 1 : 0); 101 if(in[i] == 0) Q.push(i); 102 } 103 int now, p, delta; 104 while(!Q.empty()){ 105 p = Q.front(); 106 Q.pop(); 107 for(int i = 0; i < T[p].size(); i ++){ 108 now = T[p][i].se.fi; 109 delta = (cover[now] ? 1 : 0); 110 if(dp[now] < dp[p] + delta){ 111 dp[now] = dp[p] + delta; 112 cc[now] = cc[p] + T[p][i].fi; 113 pre[now] = T[p][i].se.se; 114 } 115 else if(dp[now] == dp[p] + delta){ 116 if(cc[now] > cc[p] + T[p][i].fi){ 117 cc[now] = cc[p] + T[p][i].fi; 118 pre[now] = T[p][i].se.se; 119 } 120 } 121 in[now] --; 122 if(in[now] == 0){ 123 Q.push(now); 124 } 125 } 126 } 127 int mmi = 0; 128 LL ccc = INF; 129 for(int i = 1; i <= n; i ++){ 130 if(mmi < dp[i]){ 131 mmi = dp[i]; 132 ccc = cc[i]; 133 ddir = i; 134 } 135 else if(mi == dp[i]){ 136 if(cc[i] < ccc){ 137 cc[i] = ccc; 138 ddir = i; 139 } 140 } 141 } 142 find(ddir); 143 cout << num << endl; 144 for(int i = 1; i <= num; i ++){ 145 cout << path[i] << ' '; 146 } 147 return 0; 148 }