1 solutions

  • 1
    @ 2025-12-27 13:00:03

    *E diff 1301

    floyd 搜索
    注意到必经边 kk 非常小,于是直接枚举经过顺序。求距离使用floyd。注意每条边可以正着或反着走。

    #include<bits/stdc++.h>
    using namespace std;
    #define int long long
    int n,m,kk,ans;
    const int N=401;
    int dp[N][N];
    int usd[N];
    int ord[N];
    int mhash1[N];
    int mhash2[N];
    struct node
    {
    	int x;
    	int y;
    	int z;
    }edge[1000005];
    void dfs2(int k)
    {
    	if(k==kk+1)
    	{
    		int sum=0;
    		int st=1;
    		int ed=0;
    		for(int i=1;i<=kk;i++)
    		{
    			int x=edge[ord[i]].x;
    			int y=edge[ord[i]].y;
    			if(mhash2[i]==-1)
    			swap(x,y);
    			ed=x;
    			sum+=dp[st][ed];
    			st=y;
    		}
    		sum+=(dp[st][n]);
    		ans=min(ans,sum);
    		return ;
    	}
    	mhash2[k]=1;
    	dfs2(k+1);
    	mhash2[k]=-1;
    	dfs2(k+1);
    }
    void dfs1(int k)
    {
    	if(k==kk+1)
    	{
    		dfs2(1);
    		return ;
    	}
    	for( int i=1;i<=kk;i++ )
    	if(!mhash1[i])
    	{
    		mhash1[i]=1;
    		ord[k]=usd[i];
    		dfs1(k+1);
    		mhash1[i]=0;
    	}
    }
    signed main()
    {
    	cin>>n>>m;
    	for(int i=1;i<=n;i++)
    		for(int j=1;j<=n;j++)
    			dp[i][j]=1e15;
    	for(int i=1;i<=n;i++)
    		dp[i][i]=0;
    	for(int i=1;i<=m;i++)
    	{
    		int x,y,z;
    		cin>>x>>y>>z;
    		edge[i].x=x;
    		edge[i].y=y;
    		edge[i].z=z;
    		dp[x][y]=min(dp[x][y],z);
    		dp[y][x]=min(dp[y][x],z);
    	}
    	for(int k=1;k<=n;k++)
    		for(int i=1;i<=n;i++)
    			for(int j=1;j<=n;j++)
    				dp[i][j]=min(dp[i][j],dp[i][k]+dp[k][j]);
    	int T;
    	cin>>T;
    	while(T--)
    	{
    		cin>>kk;
    		ans=1e13;
    		int jishu=0;
    		for(int i=1;i<=kk;i++)
    		{
    			cin>>usd[i];
    			jishu+=edge[usd[i]].z;
    		}
    		dfs1(1);
    		cout<<jishu+ans<<endl;
    	}
    	return 0;
    }
    

    Information

    ID
    254
    Time
    1000ms
    Memory
    256MiB
    Difficulty
    10
    Tags
    (None)
    # Submissions
    2
    Accepted
    1
    Uploaded By