5797: 道路重建
时间限制: 1 Sec 内存限制: 128 MB提交: 65 解决: 23
[ 提交][ 状态][ 讨论版]
题目描述
小L的家乡最近遭遇了一场洪水,城市变得面目全非,道路也都被冲毁了。生活还要继续,于是市政府决定重建城市中的道路。
在洪水到来前,城市中共有n个区域和m条连接这些区域的双向道路, 道路连通了所有的区域,为了方便人们的出行,只能重建这些原有的道路, 不能建新的道路。编号为s的区域是市政广场,市政府希望重建的道路能够 使得所有区域到市政广场的最短路与受灾前保持不变,同时为了节约救灾 经费,还要使得修建的所有道路的长度和尽可能小。
小L为了拯救心爱的家乡,决定站出来,成为优秀的青年理论计算机科 学家,于是马上投入到了对这个问题的研究中。你能帮帮小L吗?
在洪水到来前,城市中共有n个区域和m条连接这些区域的双向道路, 道路连通了所有的区域,为了方便人们的出行,只能重建这些原有的道路, 不能建新的道路。编号为s的区域是市政广场,市政府希望重建的道路能够 使得所有区域到市政广场的最短路与受灾前保持不变,同时为了节约救灾 经费,还要使得修建的所有道路的长度和尽可能小。
小L为了拯救心爱的家乡,决定站出来,成为优秀的青年理论计算机科 学家,于是马上投入到了对这个问题的研究中。你能帮帮小L吗?
输入
第一行两个整数n和m,表示区域与道路的个数。
接下来m行,每行三个正整数u,v和w,描述一条连接u和v、长为w的道路。
最后一行,一个正整数s,表示市政广场的编号。
接下来m行,每行三个正整数u,v和w,描述一条连接u和v、长为w的道路。
最后一行,一个正整数s,表示市政广场的编号。
输出
输出一个整数,表示最小长度和。
样例输入
5 7
1 2 1
2 3 4
2 4 2
4 3 2
5 2 2
4 5 1
5 1 1
2
样例输出
6
提示
最优方案是重建1-2,1-5,2-4,4-3的道路,此时所有区域到达区域2的最短路分别是1, 0, 4, 2, 2,道路长度和是1 + 1 + 2 + 2 = 6。
对于20%的数据,n ≤ 10, m ≤ 20;
对于另外30%的数据,边权不超过2;
对于100%的数据,1 ≤ n ≤ 105, n − 1 ≤ m ≤ 2 ∗ 105, 1 ≤ w ≤ 109。
图论题,最不喜欢做图论了,代码又臭又长,还不好dubug.太菜
题意:给你一个图,让你选择一部分边,使中间某点到其他地方的最短距离不变,然后求最小的代价,就是跑个最短路,再跑个prim就好了。
struct node{
int u;
int v;
int dist;
int next;
}no[400005];
long long dist[100005];
long long dist1[100005];
int head[100005];
int vis[100005];
int cnt,n,m;
void add(int u,int v,int dis)
{
no[cnt].u=u;
no[cnt].v=v;
no[cnt].dist=dis;
no[cnt].next=head[u];
head[u]=cnt++;
}
void spfa(int s)
{
queue<int>q;
memset(dist,INF,sizeof(dist));
memset(vis,0,sizeof(vis));
q.push(s);
dist[s]=0;
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=no[i].next)
{
int v=no[i].v;
if(dist[v]>dist[u]+no[i].dist)
{
dist[v]=dist[u]+no[i].dist;
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
}
void XJBP(int s)
{
queue<int>q;
memset(vis,0,sizeof(vis));
memset(dist1,INF,sizeof(dist1));
for(int i=head[s];i!=-1;i=no[i].next)
{
int v=no[i].v;
dist1[v]=dist[v];
}
dist1[s]=0;
q.push(s);
while(!q.empty())
{
int u=q.front();
q.pop();
vis[u]=0;
for(int i=head[u];i!=-1;i=no[i].next)
{
int v=no[i].v;
if(dist[u]+no[i].dist==dist[v])//如果可以从这个点过来 而且等于最短距离
{
if(no[i].dist<dist1[v])//如果代价可以减少
dist1[v]=no[i].dist;
if(!vis[v])
{
vis[v]=1;
q.push(v);
}
}
}
}
}
int main ()
{
cnt=0;
scanf("%d%d",&n,&m);
memset(head,-1,sizeof(head));
for(int i=0;i<m;i++)
{
int x,y,d;
scanf("%d%d%d",&x,&y,&d);
add(x,y,d);
add(y,x,d);
}
int temp;
scanf("%d",&temp);
spfa(temp);
XJBP(temp);
long long ans=0;
for(int i=1;i<=n;i++)
{
ans=ans+dist1[i];
}
printf("%lld\n",ans);
return 0;
}