题意:有n个城市m条路。从1出发回到1,要访问选定的几个城市,这几个城市可以打工,
但是打工需要用di买执照,打工可以挣ci。问能不能访问所有选定的城市并且拿到所有执照。
分析:
1、先用floyd预处理出任意两点之间的最短距离,然后dfs搜。
2、要注意的是判断重边,n<=100,m<=5000,很明显m>=2*n。
#include<cstdio>
#include<cstring>
#include<iostream>
#define INF 10000000
using namespace std;
int e[110][110];
bool vis[110];
int n,h,money,flag;
struct choose
{
int id,c,d;
}node[20];
int minn(int x,int y)
{
return x<y?x:y;
}
void init()
{
for(int i=0;i<=n;i++)
{
for(int j=0;j<=n;j++)
{
if(i==j)
e[i][j]=0;
else
e[i][j]=INF;
}
}
memset(vis,0,sizeof(vis));
flag=0;
}
bool dfs(int x,int cnt)
{
if(cnt==h)
{
if(money-e[x][1]>=0)
return true;
}
for(int i=0;i<h;i++)
{
if(e[x][node[i].id]!=INF && money-e[x][node[i].id]>=node[i].d)
{
if(!vis[node[i].id])
{
vis[node[i].id]=true;
money=money-e[x][node[i].id]-node[i].d+node[i].c;
if(dfs(node[i].id,cnt+1))
return true;
vis[node[i].id]=false;
money=money+e[x][node[i].id]+node[i].d-node[i].c;
}
}
}
return false;
}
int main()
{
int T,m,a,b,cc;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&m,&money);
init();
for(int i=0;i<m;i++)
{
scanf("%d%d%d",&a,&b,&cc);
if(a!=b)
{
e[a][b]=minn(e[a][b],cc);
e[b][a]=minn(e[b][a],cc);
}
}
scanf("%d",&h);
for(int i=0;i<h;i++)
scanf("%d%d%d",&node[i].id,&node[i].c,&node[i].d);
for(int k=1;k<=n;k++)
{
for(int i=1;i<=n;i++)
{
for(int j=1;j<=n;j++)
{
if(e[i][k]+e[k][j]<e[i][j])
e[i][j]=e[i][k]+e[k][j];
}
}
}
if(dfs(1,0))
puts("YES");
else puts("NO");
}
return 0;
}