题意:不想说了。。。
我们只需要关心被选择的点,先预处理出来每两点间的最短路,然后问题就变成找到一条从1出发最后回到1且经过所有被选择点的最长路径,赤裸裸的TSP问题,状态压缩可破之。
最初写了个spfa,但是效率无比低,其实对于这种特殊的状态转移(只能小的向大的转移),可以直接递推。
1 #include<cstdio> 2 #include<cstring> 3 #include<cmath> 4 #include<cstdlib> 5 #include<algorithm> 6 #include<iostream> 7 #include<string> 8 #include<vector> 9 #include<queue> 10 #include<stack> 11 #include<set> 12 #include<map> 13 #include<bitset> 14 using namespace std; 15 typedef long long ll; 16 typedef pair<int,int> pii; 17 const int N=110; 18 const int M=20; 19 const int inf=~0u>>2; 20 int dp[M][1<<16]; 21 bool vis[M][1<<16]; 22 int d[N][N],dis[M][M]; 23 int hash[M],C[M],D[M],h; 24 struct node{ 25 int cur,mask,val; 26 node(){} 27 node(int _cur,int _mask,int _val): 28 cur(_cur),mask(_mask),val(_val){} 29 }; 30 bool solve(int Money){ 31 for(int i=0;i<h;i++) 32 for(int j=0;j<1<<h;j++) 33 dp[i][j]=-inf; 34 for(int i=0;i<h;i++) 35 if(Money-d[1][hash[i]]-D[i]>=0) 36 dp[i][1<<i]=max(dp[i][1<<i],Money-d[1][hash[i]]-D[i]+C[i]); 37 for(int mask=0;mask<1<<h;mask++){ 38 for(int i=0;i<h;i++){ 39 if(dp[i][mask]==-inf)continue; 40 for(int j=0;j<h;j++){ 41 if(j==i)continue; 42 if(dp[i][mask]<dis[i][j])continue; 43 if(!mask&(1<<j))continue; 44 if(dp[i][mask]-dis[i][j]-D[j]<0)continue; 45 dp[j][mask|(1<<j)]=max(dp[j][mask|(1<<j)],dp[i][mask]-dis[i][j]-D[j]+C[j]); 46 } 47 } 48 } 49 int ans=-inf; 50 for(int i=0;i<h;i++) 51 ans=max(ans,dp[i][(1<<h)-1]-dis[1][hash[i]]); 52 return ans>=0; 53 } 54 int main(){ 55 int T,n,m,Money;scanf("%d",&T); 56 while(T--){ 57 scanf("%d%d%d",&n,&m,&Money); 58 for(int i=1;i<=n;i++) 59 for(int j=1;j<=n;j++) 60 d[i][j]=i==j?0:inf; 61 for(int i=1;i<=m;i++){ 62 int u,v,len;scanf("%d%d%d",&u,&v,&len); 63 d[u][v]=d[v][u]=min(d[u][v],len); 64 } 65 for(int k=1;k<=n;k++) 66 for(int i=1;i<=n;i++) 67 for(int j=1;j<=n;j++) 68 if(d[i][k]!=inf&&d[k][j]!=inf) 69 d[i][j]=min(d[i][j],d[i][k]+d[k][j]); 70 scanf("%d",&h); 71 int start=-1; 72 for(int i=0;i<h;i++){ 73 scanf("%d%d%d",&hash[i],&C[i],&D[i]); 74 if(hash[i]==1)start=i; 75 } 76 bool flag=0; 77 for(int i=0;i<h;i++) 78 for(int j=0;j<h;j++){ 79 dis[i][j]=d[hash[i]][hash[j]]; 80 if(dis[i][j]==inf)flag=1; 81 } 82 puts(flag||!solve(Money)?"NO":"YES"); 83 } 84 return 0; 85 }