Aizu - 2249
题意:国王本来有一个铺路计划,后来发现太贵了,决定删除计划中的某些边,但是有2个原则,1:所有的城市必须能达到。 2:城市与首都(1号城市)之间的最小距离不能变大。 并且在这2个原则下使得建路消耗最小。
题解:现在来分析一下,使得n个点联通至少需要n-1条路,然后因为求最小消耗,所以路最多也就只有n-1条,除了首都以外,每一个都市都对应着一条路,我们只需要在dijkstra求最短路的时候,每次更新最短路的距离就更新这个点所对应的边,最后每个城市的点对应的边就是符合要求的边,最后求和一下就是答案了。
1 #include2 #include 3 #include 4 #include 5 #include 6 using namespace std; 7 #define ll long long 8 typedef pair<int, int> pll; 9 const int INF = 0x3f3f3f3f; 10 const int N = 10000+5; 11 struct Node 12 { 13 int nt, to, d, c; 14 }Edge[N*4]; 15 int head[N], dis[N], pre[N]; 16 int cnt = 0, n, m; 17 void add(int u, int v, int d, int c) 18 { 19 Edge[cnt].to = v; 20 Edge[cnt].d = d; 21 Edge[cnt].c = c; 22 Edge[cnt].nt = head[u]; 23 head[u] = cnt++; 24 } 25 void dijkstra() 26 { 27 memset(dis, INF, sizeof(dis)); 28 dis[1] = 0; 29 priority_queue , greater > q; 30 q.push(pll(0,1)); 31 while(!q.empty()) 32 { 33 int u = q.top().second, d = q.top().first; 34 q.pop(); 35 if(dis[u] != d) continue; 36 for(int i = head[u]; ~i; i = Edge[i].nt) 37 { 38 int v = Edge[i].to; 39 if(dis[v] > dis[u] + Edge[i].d) 40 { 41 dis[v] = dis[u] + Edge[i].d; 42 pre[v] = i; 43 q.push(pll(dis[v],v)); 44 } 45 else if(dis[v] == dis[u]+Edge[i].d && Edge[i].c < Edge[pre[v]].c) 46 { 47 pre[v] = i; 48 q.push(pll(dis[v],v)); 49 } 50 } 51 } 52 } 53 int main() 54 { 55 ios::sync_with_stdio(false); 56 cin.tie(0); 57 cout.tie(0); 58 while(cin >> n >> m, n+m) 59 { 60 memset(head, -1, sizeof(head)); 61 cnt = 0; 62 int x, y, d, c; 63 for(int i = 0; i < m; i++) 64 { 65 cin >> x >> y >> d >> c; 66 add(x,y,d,c); 67 add(y,x,d,c); 68 } 69 dijkstra(); 70 ll ans = 0; 71 for(int i = 2; i <= n; i++) 72 { 73 ans += Edge[pre[i]].c; 74 } 75 cout << ans << endl; 76 } 77 return 0; 78 }