ZOJ-3946 Highway Project (最短路)

题目大意:一张带权无向图,权有两个参数(d,c),分别表示走过这条边的时间和建造这条边的代价。要求选出一些边,使得0节点到其他点的距离之和最短,并在最短的基础上求最小代价。

题目分析:这是16年浙江省赛的一道题。先求出0到所有点的最短路,然后找出所有可能在最短路径上的边,最后在每一个节点的入边之中都选一条具有最小代价的边。多么简单的一道题!!!

 

代码如下:

# include<iostream>
# include<cstdio>
# include<cstring>
# include<vector>
# include<queue>
# include<list>
# include<set>
# include<map>
# include<string>
# include<cmath>
# include<cstdlib>
# include<algorithm>
using namespace std;
# define LL long long

const int N=1005;
const int INF=1000000000;
const LL oo=1000000000000005;

struct Edge
{
	int to,nxt;
	LL c,d;
};

int n,m,cnt;
Edge e[N*200];
LL d[N*100];
int head[N*100];
vector<int>pre[N*100];

void add(int u,int v,LL d,LL c)
{
	e[cnt].to=v;
	e[cnt].d=d;
	e[cnt].c=c;
	e[cnt].nxt=head[u];
	head[u]=cnt++;
}

void solve()
{
	for(int i=0;i<n;++i)
		pre[i].clear();
	
	fill(d,d+n,oo);
	d[0]=0;
	queue<int>q;
	q.push(0);
	while(!q.empty())
	{
		int u=q.front();
		q.pop();
		for(int i=head[u];i!=-1;i=e[i].nxt){
			int v=e[i].to;
			if(d[v]>d[u]+e[i].d){
				d[v]=d[u]+e[i].d;
				q.push(v);
			}
		}
	}
	
	q.push(0);
	while(!q.empty()){
		int u=q.front();
		q.pop();
		for(int i=head[u];i!=-1;i=e[i].nxt){
			int v=e[i].to;
			if(d[v]==d[u]+e[i].d){
				pre[v].push_back(i);
				q.push(v);
			}
		}
	}
	
	LL ans1=0,ans2=0;
	for(int i=0;i<n;++i){
		ans1+=d[i];
		LL minn=oo;
		for(int j=0;j<pre[i].size();++j)
			minn=min(minn,e[pre[i][j]].c);
		if(minn==oo) continue;
		ans2+=minn;
	}
	printf("%lld %lld\n",ans1,ans2);
}

int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d%d",&n,&m);
		cnt=0;
		memset(head,-1,sizeof(head));
		int a,b;
		LL c,d;
		for(int i=0;i<m;++i){
			scanf("%d%d%lld%lld",&a,&b,&d,&c);
			add(a,b,d,c);
			add(b,a,d,c);
		}
		solve();
	}
	return 0;
}

  

posted @ 2016-04-24 09:53  20143605  阅读(959)  评论(0编辑  收藏  举报