【圖的再構造】 uva 10917

題目大意:一張無向圖上面有Jimmy的家和Jimmy的公司。

Jimmy必須要走滿足一下條件的路:如果Jimmy要從A走到B,必須存在一條以B爲起點的路徑,比從任何一條以A爲起點的路徑短。

 

思路:所謂的“必須存在一條以B爲起點的路徑,比從任何一條以A爲起點的路徑短。” 也就是說,從A開始的最短路徑比從B開始的最短路徑短。 因此跑完一邊最短路徑後,我們對所有d[x] > d[y]的點對建立一條邊。

 

得到的新的圖必然是一棵樹(想一想,爲什麼?)

然後跑一邊一個很簡單的樹上dp就可以了。

 

#include <bits/stdc++.h>
#define CLR(arr) memset(arr,0,sizeof(arr))
using namespace std;
const int maxn = 1020;
typedef long long ll;

struct HeapNode{
	int u,d;
	bool operator < (const HeapNode& rhs) const
	{
		return d > rhs.d;	
	} 
};
struct Edge{
	int u,v,dist;
};

int ecnt;
int d[maxn];
int p[maxn];
bool done[maxn];
vector<int> G[maxn];
vector<Edge> edge;

void AddEdge(int u, int v, int dist)
{
	edge.push_back(Edge{u,v,dist});
	G[u].push_back(ecnt++);
}

void dijkstra(int s)
{
	CLR(done);
	memset(d,0x3f,sizeof(d));
	
	d[s] = 0;

	priority_queue<HeapNode> Q;
	Q.push(HeapNode{s,0});
	while(!Q.empty())	
	{
		HeapNode x = Q.top(); Q.pop();
		int u = x.u;
		if(done[u]) continue;
		done[u] = true;
		
		for (int i = 0 ; i < G[u].size() ;++i)
		{
			Edge &e = edge[G[u][i]];
			if(d[e.v] > d[u] + e.dist)
			{
				d[e.v] = d[u] + e.dist;
				p[e.v] = u;	
				Q.push(HeapNode{e.v,d[e.v]});
			} 	
		} 
	}
}

int F[maxn];
vector<int> tree[maxn];
void init(int n){
	CLR(p);
	CLR(F);
	for (int i = 0 ; i < n ; ++i) G[i].clear();
	for (int i = 0 ; i < n ; ++i) tree[i].clear(); 
	edge.clear();
	ecnt = 0;
}



int dp(int k)
{
	if(k == 0) return 1;
	if(F[k] != -1) return F[k];
	int& ret = F[k];
	ret = 0;
	for (int i = 0 ; i < tree[k].size() ; ++i)
	{
		int v = tree[k][i]; 
		ret += dp(v);
	}
	return ret;
}


bool vis[maxn];

int main()
{
	int n,m;
	while(cin >> n )
	{
		if(n==0) break;
		cin >> m;
		int a,b,t;
		init(n);
		for (int i = 0 ; i < m ; ++i)
		{
			cin >> a >> b >> t;
			a--;b--;
			AddEdge(a,b,t);
			AddEdge(b,a,t);
		}

		dijkstra(2-1);
		CLR(vis);

		memset(F,-1,sizeof(F));
		for (int u = 0 ; u < n ; ++u)	
			for (int i = 0 ; i < G[u].size() ; ++i)
			{
				Edge &e = edge[G[u][i]];
				int v = e.v;
				if(d[v] > d[u])
					tree[u].push_back(v);				
			}
		
		int ans = 0;
		ans = dp(1);
		cout << ans << endl;
	}
	return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章