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;
}
题意:给一个无向图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;
}
相关文章推荐
- Vmware虚拟机下精简版RedHat Linux安装GCC
- Eclipse开发环境搭建
- 在Window Embedded CE(Wince)下使用OpenNETCF进行路由表的开发
- Android下的自定义日志框架
- 在Window Embedded CE(Wince)下使用OpenNETCF进行路由表的开发
- 读《认知与设计:理解UI设计准则》第三章
- python 笔记2
- Qt thread and eventloop
- 10月19日 html学习笔记(1)
- Eclipse快捷键总结
- Mysql中文乱码的问题
- 类继承
- 数组的介绍以及其详细使用需要注意的地方
- Bootstrap插件modal源码的学习
- java将xml解析,然后将其转换为json格式(1)
- SearchView小结
- 工作笔记10
- 学生成绩管理系统
- POJ 1595 Prime Cuts(素数切)
- java 多态性