题意:给你一幅图,问有多少条路径使得去掉该条路后最短路发生变化。
思路:先起始两点求两遍单源最短路,利用s[u] + t[v] + G[u][v] = dis 找出所有最短路径,构造新图。在新图中找到所有的桥输出就可以了。
1 #include <iostream> 2 #include <cstdio> 3 #include <fstream> 4 #include <algorithm> 5 #include <cmath> 6 #include <deque> 7 #include <vector> 8 #include <queue> 9 #include <string> 10 #include <cstring> 11 #include <map> 12 #include <stack> 13 #include <set> 14 #define LL long long 15 #define eps 1e-8 16 #define INF 0x3f3f3f3f 17 #define MAXN 20005 18 #define MAXM 100005 19 using namespace std; 20 21 struct Edge 22 { 23 int from, to, dist, pos; 24 Edge(int from, int to, int dist, int pos) :from(from), to(to), dist(dist), pos(pos){}; 25 }; 26 struct HeapNode 27 { 28 int d, u; 29 HeapNode(int d, int u) :d(d), u(u){}; 30 bool operator <(const HeapNode& rhs) const{ 31 return d > rhs.d; 32 } 33 }; 34 struct Dijstra 35 { 36 int n, m; 37 vector<Edge> edges; 38 vector<int> G[MAXN]; 39 bool done[MAXN]; 40 int d[MAXN]; 41 int p[MAXN]; 42 43 void init(int n){ 44 this->n = n; 45 for (int i = 0; i <= n; i++){ 46 G[i].clear(); 47 } 48 edges.clear(); 49 } 50 51 void AddEdge(int from, int to, int dist, int pos = 0){ 52 edges.push_back(Edge(from, to, dist, pos)); 53 m = edges.size(); 54 G[from].push_back(m - 1); 55 } 56 57 void dijstra(int s){ 58 priority_queue<HeapNode> Q; 59 for (int i = 0; i <= n; i++){ 60 d[i] = INF; 61 } 62 d[s] = 0; 63 memset(done, 0, sizeof(done)); 64 Q.push(HeapNode(0, s)); 65 while (!Q.empty()){ 66 HeapNode x = Q.top(); 67 Q.pop(); 68 int u = x.u; 69 if (done[u]) continue; 70 done[u] = true; 71 for (int i = 0; i < G[u].size(); i++){ 72 Edge& e = edges[G[u][i]]; 73 if (d[e.to] > d[u] + e.dist){ 74 d[e.to] = d[u] + e.dist; 75 p[e.to] = G[u][i]; 76 Q.push(HeapNode(d[e.to], e.to)); 77 } 78 else if (d[e.to] == d[u] + e.dist){ 79 80 } 81 } 82 } 83 } 84 }; 85 int pre[MAXN], isbridge[MAXM], low[MAXN]; 86 vector<Edge> G[MAXN]; 87 int dfs_clock; 88 int dfs(int u, int father){ 89 int lowu = pre[u] = ++dfs_clock; 90 //int child = 0; 91 for (int i = 0; i < G[u].size(); i++){ 92 int v = G[u][i].to; 93 if (!pre[v]){ 94 //child++; 95 int lowv = dfs(v, G[u][i].pos); 96 lowu = min(lowu, lowv); 97 if (lowv > pre[u]){ 98 isbridge[G[u][i].pos] = true; 99 } 100 } 101 else if (pre[v] < pre[u] && G[u][i].pos != father){ 102 lowu = min(lowu, pre[v]); 103 } 104 } 105 low[u] = lowu; 106 return lowu; 107 } 108 Dijstra s, t; 109 vector<Edge> edges; 110 111 int res[MAXM]; 112 int main() 113 { 114 #ifdef ONLINE_JUDGE 115 freopen("important.in", "r", stdin); 116 freopen("important.out", "w", stdout); 117 #endif // OPEN_FILE 118 int n, m; 119 while (~scanf("%d%d", &n, &m)){ 120 s.init(n); 121 t.init(n); 122 edges.clear(); 123 int x, y, z; 124 for (int i = 1; i <= m; i++){ 125 scanf("%d%d%d", &x, &y, &z); 126 edges.push_back(Edge(x, y, z, i)); 127 edges.push_back(Edge(y, x, z, i)); 128 s.AddEdge(x, y, z); 129 s.AddEdge(y, x, z); 130 t.AddEdge(x, y, z); 131 t.AddEdge(y, x, z); 132 } 133 s.dijstra(1); 134 t.dijstra(n); 135 LL dis = s.d[n]; 136 //把所有最短路径找出来,在里面找出所有的桥就是答案 137 for (int i = 0; i < edges.size(); i++){ 138 Edge e = edges[i]; 139 if (s.d[e.from] + e.dist + t.d[e.to] == dis){ 140 G[e.from].push_back(Edge(e.from, e.to, e.dist, e.pos)); 141 G[e.to].push_back(Edge(e.to, e.from, e.dist, e.pos)); 142 143 } 144 } 145 dfs_clock = 0; 146 memset(isbridge, 0, sizeof(isbridge)); 147 memset(pre, 0, sizeof(pre)); 148 dfs(1, -1); 149 int ans = 0; 150 for (int i = 1; i <= m; i++){ 151 if (isbridge[i]){ 152 ans++; 153 res[ans] = i; 154 } 155 } 156 printf("%d\n", ans); 157 for (int i = 1; i <= ans; i++){ 158 printf("%d ", res[i]); 159 } 160 printf("\n"); 161 } 162 }
时间: 2024-10-08 10:03:51