Shu Chuan's going to the meeting alone

Posted by Bladescope on Fri, 18 Feb 2022 21:46:05 +0100

Problem surface

Description

[title background]
In 215 ad, Liu Bei took Yizhou, and Sun Quan ordered Zhuge Jin to ask Liu Bei for Jingzhou. Liu Bei refused, and Sun Quan was so angry that he sent LV Meng to lead the army to take Changsha, Lingling and Guiyang. Changsha, Guiyang and Shu will surrender immediately. After learning that, Liu Bei personally rushed to the public security (now Hubei public security) from Chengdu and sent General Guan Yu to compete for the three counties. Sun Quan also immediately stationed in Lukou and sent Lu Su to garrison Yiyang to resist Guan Yu. At this critical juncture, Lu Su decided to discuss with Guan Yu face-to-face in order to protect the sun Liu alliance. "Su invited Yu to meet each other, and each soldier and horse stationed on a hundred steps, but all generals can master single Sabre". After talks, the two sides eased the tension. Subsequently, Sun Quan and Liu Bei agreed to divide Jingzhou equally. "Cut the Xiangshui River as the boundary, so they stopped the army". Therefore, the sun Liu alliance can continue to maintain.

[problem description]
Guan Yu was invited by Lu su. For the sake of the overall situation, he decided to take a risk to attend the meeting. He set out from the military camp with his attendant Zhou Cang and adopted son Guan Ping, riding a red rabbit horse and holding a green dragon Yanyue knife. This is the famous "going to the meeting alone" in history. Guan Yu decided to visit some good friends he hadn't seen for many days on this trip because of heavy military affairs. However, the situation is tense. This trip should be completed within a limited time. Guan Gong hopes you can help him arrange the trip and arrange a way of travel, so that he can start from the military camp, arrive at Lu Su for the meeting and then come back, and visit as many friends as possible. The trip is the shortest under these conditions. Pay attention to visiting friends before or after the party. Now give the map, please complete the next task.

Input

The first line n,m,k,t represents n places, m roads, k friends (excluding Lu Su), and the limited time t (it takes 1 unit time to walk a distance of 1 unit length).
In the next m lines, each line has three integers x, y and W, representing that there is a road with a length of w between X and y.
There are k integers in the next line, representing the capital number of the friend (ensure that they are different and not between 1 and n)
(we agreed that 1 is Guan Yu's camp and n is Lu Su's camp)

Output

Output two integers, which are the maximum number of friends you can visit and the minimum time you need in this case. If you can't even reach Lu Su and come back, output a - 1.

Sample Input

5 7 2 15
1 2 5
1 3 3
2 3 1
2 4 1
3 4 4
2 5 2
4 5 3
2 4

Sample Output

2 14

Data Constraint

There are 10% data, n < = 10, m < = 50, K < = 5;
With 10% data, k=0;
With 10% data, k=1;
Another 30% data, K < = 5;
For 100% data, n < = 10000, m < = 50000, K < = 15, T < = 2147483647, w < = 10000

thinking

See this question k ≤ 15 k\le15 k ≤ 15, I thought of the pressure, but I didn't push out the test (tears

Positive solution or pressure.
First, let's run through all the key points (where our friends are) s p f a spfa spfa, preprocess the shortest path from each key point to other key points. Why do you do this? It will be mentioned later when we talk about the pressure.
We consider setting f s , i f_{s,i} fs,i , indicates that the status of the current key point is s (1 for passing through and 0 for not passing through). On the ith key point, set i i i to j j The shortest circuit of j is r o a d i , j road_{i,j} roadi,j​. The transfer is obvious.
f s ∣ ( 1 < < j ) , j = m i n { f s , i + r o a d i , j } w h e n { ( s & 1 < < i )   a n d   ( ! ( s & ( 1 < < j ) ) ) } f_{s|(1<<j),j}=min\{f_{s,i}+road_{i,j}\}\\ when\{(s\&1<<i)\ and\ (!(s\&(1<<j)))\} fs∣(1<<j),j​=min{fs,i​+roadi,j​}when{(s&1<<i) and (!(s&(1<<j)))}
Finally, enumerate the status and key points to find the answer.

Code

#include<cstdio>
#include<iostream>
#include<cmath>
#include<cstring>
#define N 100005
using namespace std;
int cnt,head[N],next[N],to[N],ti[N];
int q[6000005],flag[N],dis[N],fr[N];
int n,m,k,tt,road[20][20];
int f[150000][20],ans1,ans2=99999999;
void add(int u,int v,int ds) {
	next[++cnt]=head[u];
	head[u]=cnt;
	ti[cnt]=ds;
	to[cnt]=v;
}
void spfa(int from,int number) {
	int t=0,w=1;
	memset(flag,0,sizeof(flag));
	memset(dis,0x3f,sizeof(dis));
	flag[from]=1;dis[from]=0;
	q[w]=from;
	while(t<w) {
		t++;
		int u=q[t];
		flag[u]=0;
		for(int i=head[u];i;i=next[i]) {
			int v=to[i];
			if(dis[v]>dis[u]+ti[i]) {
				dis[v]=dis[u]+ti[i];
				if(!flag[v]) {
					flag[v]=1;
					q[++w]=v;
				}
			}
		}
	}
	for(int i=0;i<=k;i++)
		if(i!=number) road[i][number]=road[number][i]=dis[fr[i]];
}
int main() {
	scanf("%d%d%d%d",&n,&m,&k,&tt);
	for(int i=1;i<=m;i++) {
		int u,v,ds;
		scanf("%d%d%d",&u,&v,&ds);
		add(u,v,ds),add(v,u,ds);
	}
	for(int i=1;i<=k;i++)
		scanf("%d",&fr[i]);
	fr[0]=1,fr[++k]=n;
	for(int i=0;i<=k;i++)
		spfa(fr[i],i);
	memset(f,0x3f,sizeof(f));
	f[1][0]=0;
	for(int s=0;s<=(1<<k+1)-1;s++)
		for(int i=0;i<=k;i++)
			for(int j=0;j<=k;j++)
				if(i!=j&&(s&(1<<i))&&(!(s&(1<<j))))
					f[s|(1<<j)][j]=min(f[s|(1<<j)][j],f[s][i]+road[i][j]);
	for(int s=0;s<=(1<<k+1)-1;s++)
		for(int i=0;i<=k;i++)
			if(f[s][i]+road[i][0]<=tt&&(s&1)&&(s&(1<<k))&&(s&(1<<i))) {
				int x=0;
				for(int j=0;j<=k;j++)
					if(s&(1<<j)) x++;
				if(x==ans1) ans2=min(ans2,f[s][i]+road[i][0]);
				if(x>ans1) ans1=x,ans2=f[s][i]+road[i][0];
			}
	if(ans2!=f[0][0]) printf("%d %d",ans1-2,ans2);
	else printf("-1");
}

Topics: Graph Theory dp