问题详情:
Rashof是EMLand的市长。 EMLand由交叉路口和街道组成。从每个交叉口到任何其他交叉口只有一条路径。交叉点由正整数1 ... n表示。
一家建筑公司已经提供Rashof重建EMLand的所有街道,但Rashof可以选择at most k of them to be rebuilt.
建筑公司为每条街道提供了一个新的长度,这意味着在街道重建之后,街道的长度会发生变化。
现在作为城市市长的Rashof必须明智地选择,以便最小化所有交叉路口之间的路径长度。
帮助Rashof!
算法:
符号:旧边长为L
,新长度为L'
,边距为E
。
C
)长度将减少的edges(E')
的数量,即L'<大号C
小于或等于K
,则为
考虑所有边缘(E'),即更新E 其他
1。基于(L'L)按升序对所有边(E')进行排序
2。按照L'的降序顺序对那些(L'-L)相同的边(E''E')进行排序
3.选择第一个K边(E''E')并更新E中所有这些边的长度
使用边E和长度L构建图G
使用优先级队列和Dijkstra算法实现上述算法。
#include <bits/stdc++.h>
using namespace std;
typedef pair<int,int> pii;
struct s{
int x;
int y;
int a;
int b;
int c;
};
const int MAX = 100000;
const long long INF = 100000000000000000;
vector< pii > G[MAX];
long long d[MAX];
void dijkstra(long long start) {
int u, v, i, c, w;
priority_queue< pii, vector< pii >, greater< pii > > Q;
for(i=0;i<MAX;i++){
d[i]=INF;
}
Q.push(pii(0, start));
d[start] = 0;
while(!Q.empty()) {
u = Q.top().second; // node
c = Q.top().first; // node cost so far
Q.pop(); // remove the top item.
if(d[u] < c) continue;
for(i = 0; i < G[u].size(); i++) {
v = G[u][i].first; // node
w = G[u][i].second; // edge weight
if(d[v] > d[u] + w) {
d[v] = d[u] + w;
//cout<<d[v];
Q.push(pii(d[v], v));
}
}
}
}
bool func(const s s1,const s s2) { return (s1.c < s2.c); }
bool func2(const s s1,const s s2) { return (s1.b < s2.b); }
int main() {
long long n, e, u, V, w,x,y,a,b,t,i,j,k,res,z=2;
s S;
vector<s> v;
map<pair<int,int>,int> m;
map<pair<int,int>,int>::iterator it;
cin>>t;
while(t--){
cin>>n>>k;
for(i = 1; i <= n; i++) G[i].clear();
v.clear();
m.clear();
for(i=1;i<n;i++){
cin>>x>>y>>a>>b;
if(b<a){
S.x = x;
S.y =y;
S.a=a;
S.b=b;
S.c=b-a;
v.push_back(S);
}
m[make_pair(x,y)]=a;
}
if(v.size()<=k){
for(i=0;i<v.size();i++){
m[make_pair(v[i].x,v[i].y)]=v[i].b;
}
it = m.begin();
for(;it!=m.end();++it){
u = it->first.first;
V = it->first.second;
w = it->second;
G[u].push_back(pii(V, w));
G[V].push_back(pii(u, w));
}
res = 0;
for(i=1;i<=n;i++){
dijkstra(i);
for(j= 1; j <= n; j++) {
if(i == j) continue;
if(d[j] >= INF) ;
else res+=d[j];
}
}
cout<<res/z<<"\n";
}
else{
sort(v.begin(),v.end(),func);
for(i=0;i<v.size();i++){
j = i;
while(v[i].c==v[j].c&&j<v.size())j++;
sort(v.begin()+i,v.begin()+j,func2);
i=j;
}
for(i=0;i<k;i++){
m[make_pair(v[i].x,v[i].y)]=v[i].b;
}
it = m.begin();
for(;it!=m.end();++it){
u = it->first.first;
V = it->first.second;
w = it->second;
G[u].push_back(pii(V, w));
G[V].push_back(pii(u, w));
}
res = 0;
for(i=1;i<=n;i++){
dijkstra(i);
for(j= 1; j <= n; j++) {
if(i == j) continue;
if(d[j] >= INF) ;
else res+=d[j];
}
}
cout<<res/z<<"\n";
}
}
return 0;
}
It passes only 2 test cases out of 9 test cases .
为什么这个算法不起作用?
或者在这个算法中应该做什么修改才能被接受?
的参考:
Rashof, Mayor of EMLand
答案 0 :(得分:2)
答案 1 :(得分:1)
请注意,这是一棵树,因此,每条边连接两个连接的组件。
假设我们在两个连接的组件A和B之间有边连接,它包含n和m个交叉点,因此,通过将边缘减少x个单位,我们将总距离减少n*m*x
。 / p>
A---B---C----E
| |
| |
D---- -----F
请看上图,B和C之间的边连接两个连通分量,(A,B,D)和(C,E,F),减小此边的权重会减小(A,B)之间的距离,D)和(C,E,F)
因此,算法是选择k个边,其中n*m*x
最大(如果x
为正)。