1. 程式人生 > 實用技巧 >iOS內購-收據驗證以及漏單情況的處理

iOS內購-收據驗證以及漏單情況的處理

洛谷 P1608 路徑統計

洛谷傳送門

題目描述

“RP 餐廳” 的員工素質就是不一般,在齊刷刷的算出同一個電話號碼之後,就準備讓 HZH,TZY 去送快餐了,他們將自己居住的城市畫了一張地圖,已知在他們的地圖上,有 NN 個地方,而且他們目前處在標註為 “1” 的小鎮上,而送餐的地點在標註為 “N” 的小鎮。(有點廢話)除此之外還知道這些道路都是單向的,從小鎮 II 到 JJ 需要花費 D[I, J]D[I,J] 的時間,為了更高效快捷的將快餐送到顧客手中,他們想走一條從小鎮 11 到小鎮 NN 花費最少的一條路,但是他們臨出發前,撞到因為在路上堵車而生氣的 FYY,深受啟發,不能僅知道一條路線,萬一。。。於是,他們邀請 FYY 一起來研究起了下一個問題:這個最少花費的路徑有多少條?

輸入格式

輸入檔案第一行為兩個空格隔開的數 NN,EE,表示這張地圖裡有多少個小鎮及有多少邊的資訊。

下面 EE 行,每行三個數 II、JJ、CC,表示從 II 小鎮到 JJ 小鎮有道路相連且花費為 CC.(注意,資料提供的邊資訊可能會重複,不過保證 I\not=JI=J,1 \leq I1≤I,J\leq NJN)。

輸出格式

輸出檔案包含兩個數,分別是最少花費和花費最少的路徑的總數.

兩個不同的最短路方案要求:路徑長度相同(均為最短路長度)且至少有一條邊不重合。

若城市 NN 無法到達則只輸出一個 No answer


題解:

Dij求最短路+最短路計數。

最短路計數的部落格請見:

淺談最短路計數

程式碼:

#include<cstdio>
#include<cstring>
#include<queue>
using namespace std;
const int maxn=2010;
int n,e;
int mp[maxn][maxn];
int tot,head[maxn],nxt[maxn*maxn],to[maxn*maxn],val[maxn*maxn];
void add(int x,int y,int z)
{
	to[++tot]=y;
	val[tot]=z;
	nxt[tot]=head[x];
	head[x]=tot;
}
priority_queue<pair<int,int> >q;
int dist[maxn],cnt[maxn];
bool v[maxn];
void dijkstra()
{
	memset(dist,127,sizeof(dist));
	dist[1]=0;
	cnt[1]=1;
	q.push(make_pair(0,1));
	while(!q.empty())
	{
		int x=q.top().second;
		q.pop();
		if(v[x])
			continue;
		v[x]=1;
		for(int i=head[x];i;i=nxt[i])
		{
			int y=to[i];
			if(dist[x]+val[i]<dist[y])
			{
				dist[y]=dist[x]+val[i],cnt[y]=cnt[x];
				q.push(make_pair(-dist[y],y));
			}
			else if(dist[x]+val[i]==dist[y])
				cnt[y]+=cnt[x];
		}
	}
}
int main()
{	
	scanf("%d%d",&n,&e);
	for(int i=1;i<=e;i++)
	{
		int x,y,z;
		scanf("%d%d%d",&x,&y,&z);
		if(!mp[x][y]||mp[x][y]>z)
		{
			add(x,y,z);
			mp[x][y]=z;
		}
	}
	dijkstra();
	if(dist[n]>1e9)
	{
		puts("No answer");
		return 0;
	}
	printf("%d %d",dist[n],cnt[n]);
	return 0;
}