您的位置:首页 > 其它

Codeforces#303-E - Paths and Treesg-最短路+最小生成树

2015-10-20 22:58 369 查看
http://codeforces.com/contest/545/problem/E

题意:给一个无向图G,一个起点U,要求找到一个子图,【子图中U到各点的最短路与原图相等】,求出  【所有边权之和最小的】 一个子图

输出权值和 +每条边的编号 (边按输入的顺序从一到m编号)

思路:直接求一遍最短路,得到dist[]数组

然后

 for (i=1;i<=n; i++)

{

//遍历与点i相连的所有边,如果能找到一条 边使得  【起点到i 点 的dist不变】且 【边权比原来的小】,就更新掉子图的边

}

求最小权值和这部分复杂度O(m)

求最短路(n+m)log(n)

总复杂度还是(n+m)log(n)......

#include <cstdio>
#include <cmath>
#include <cstring>
#include <string>
#include <algorithm>
#include <iostream>
#include <queue>
#include <map>
#include <set>
#include <vector>
using namespace std;
#define INF 9223372036854775807
const __int64 maxn = 300005;
struct EDGE
{
__int64 u;
__int64 x;__int64 v;
int id;
EDGE(){}
EDGE (__int64 uu,__int64 i,__int64 j,__int64 idd)
{
u=uu; x=i;v=j; id=idd;
}
bool operator < (const EDGE &b) const
{
return v>b.v;
}
};
vector <EDGE> tm[maxn];
vector <int> ans;

__int64 dist[maxn];
priority_queue<EDGE> que;
int main()
{
__int64 n,r,i,j;
__int64 a,b,c;
scanf("%I64d%I64d",&n,&r);
for (i=1;i<=n;i++)
dist[i]=INF;
for (i=1;i<=r;i++)
{
scanf("%I64d %I64d %I64d",&a,&b,&c);
tm[a].push_back(EDGE(a,b,c,i));
tm[b].push_back(EDGE(b,a,c,i));
}
__int64 st;
scanf("%I64d",&st);
dist[st]=0;
que.push(EDGE(st,st,0,-1));
__int64 minway;
__int64 minpoint;
// --------------------Dijkstra
while(!que.empty())
{
EDGE p=que.top();
que.pop();
minpoint=p.x;
minway=p.v;
// vis[minpoint]=1;//参见spfa(),用vis是把已经在queue中的点不用再push,但是此处用邻接表无法解决重边的问题,所以需要多次push,也就是不能用vis
for (i=0;i<tm[minpoint].size();i++)
{
__int64 x=tm[minpoint][i].x;
__int64 v=tm[minpoint][i].v;

if ( v+minway<dist[x] /*&&vis[x]!=1*/ )
{
dist[x]=v+minway;
que.push(EDGE(i,x,dist[x],-1)); //id=-1表示 不需要用到id
}
}

}
// 求最小权值和
__int64 sum=0;
for (i=1;i<=n;i++)
{
if (i==st) continue;
__int64 MIN=INF;
int min_EDGE_id;
for (j=0;j<tm[i].size();j++)
{
__int64 y=tm[i][j].x;
if (y==i) continue;
__int64 v=tm[i][j].v;
if (dist[i]==dist[y]+v&&v<MIN)
{
MIN=v;
min_EDGE_id=tm[i][j].id;
}
}
sum+=MIN;
ans.push_back(min_EDGE_id);

}
printf("%I64d\n",sum);
for (i=0;i<ans.size();i++)
{
if (i!=0) printf(" ");
printf("%d",ans[i]);
}
printf("\n");
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: