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 }

 

posted on 2017-10-18 20:57  poler  阅读(315)  评论(0编辑  收藏  举报

导航