新年おめでとうございます(Dijkstra+サブセット生成)


【問題の説明】
 
重慶城にはnつの駅があり、m本の双方向道路がその中のいくつかの駅を接続している.2つの駅ごとに最大1つの道路で直接接続され、どの駅からも1つ以上の道路を通って他の駅に着くことができますが、経路によって時間がかかる可能性があります.1つの経路にかかる時間は、経路上のすべての道路に必要な時間と等しい.
佳佳の家は駅にあります.彼は5人の親戚がいて、それぞれ駅a、b、c、d、eに住んでいます.年を越して、彼は自分の家を出発して、すべての親戚を訪問して(順番は任意です)、彼らに祝日の祝福を送る必要があります.どのように行って、最も少ない時間が必要ですか?
 
【入力形式】
 
1行目:n(n<=50000)、m(m<=100000)は、駅数と道路数である.
2行目:a、b、c、d、eは、5人の親戚がいる駅番号(1次にm行は、1行あたり3つの整数x、y、t(1<=x、y<=n、1<=t<=100)で、道路接続の2つの駅番号と時間である.
 
【出力形式】
 
1行のみ、整数Tを含む最小の合計時間
 
【入力サンプル】
 
6 6
2 3 4 5 6
1 2 8
2 3 3
3 4 4
4 5 5
5 6 2
1 6 7
 
【出力サンプル】
 
21
 
【データ範囲】
 
n<=50,000
m<=100,000
分析:
一、最短の問題は、自然に三大アルゴリズムを思いつく.
二、5つの点に起点を加えて全部で6つの点で、1つ目の点は1で、固定されていて、その他の点の順序は任意で、1回の処理が終わりません;しかし、全部で6つの点しかないので、各点に1回の単一ソースの最短ルートが考えられ、それぞれ1つのdist配列で記録されています.そして可能なすべての配列を列挙し、最小の経路を求めればよい.
#include
#include
#include
using namespace std;
const int maxn=50005;
const int maxm=100005;
const int INF=150000000;
int n,m,np=0,last[maxn],rela[6],dist[6][maxn];
struct edge{int to,w,pre;}E[maxm*2];
struct data
{
	int d,id;
	friend bool operator < (data a,data b) {return a.d>b.d;}
};

char c;
inline void qkscanf(int &x)
{
	for(c=getchar();c'9';c=getchar());
	for(x=0;c>='0'&&c<='9';c=getchar()) x=x*10+c-'0';
}

inline void addedge(int u,int v,int w)
{
	E[++np]=(edge){v,w,last[u]};
	last[u]=np;
}

int done[maxn];
inline void Dijkstra(int s,int *dis)
{
	priority_queuepq;
	for(int i=1;i<=n;i++) dis[i]=INF,done[i]=0;
	pq.push((data){0,s});
	dis[s]=0;
	while(!pq.empty())
	{
		data t=pq.top();pq.pop();
		int i=t.id;
		if(done[i]) continue;
		done[i]=1;
		for(int p=last[i];p;p=E[p].pre)
		{
			int j=E[p].to,w=E[p].w;
			if(dis[j]>dis[i]+w)
			{
				dis[j]=dis[i]+w;
				pq.push((data){dis[j],j});
			}
		}
	}
}

int order[6];
int ans=INF;
inline void check()
{
	int cnt=0;
	for(int i=0;i<5;i++)
	{
		int x=order[i],y=rela[order[i+1]];//i  i+1      
		cnt+=dist[x][y];
	}
	ans=min(ans,cnt);
}

int vis[6];
inline void DFS(int cnt)
{
	if(cnt>5)//        
	{
		check();
		return;
	}
	
	for(int i=1;i<=5;i++)
	{
		if(!vis[i])
		{
			vis[i]=1;
			order[cnt]=i;//    rela      ,       
			DFS(cnt+1);
			vis[i]=0;
		}
	}
}

int main()
{
//	freopen("in.txt","r",stdin);
	//input
	qkscanf(n);qkscanf(m);
	for(int i=1;i<=5;i++) qkscanf(rela[i]);
	register int u,v,w;
	for(int i=1;i<=m;i++)
	{
		qkscanf(u);qkscanf(v);qkscanf(w);
		addedge(u,v,w);addedge(v,u,w);
	}
	//solve
	rela[0]=1;//   1 
	for(int i=0;i<=5;i++) Dijkstra(rela[i],dist[i]);//        
	order[0]=0;//   ,       1(rela      0) 
	DFS(1);
	printf("%d",ans);
}