这题,初看没什么思路,下午看的时候挺困的,去床上躺了会儿,想通了,水题呀~~
给你几条路线,从一条路线到另一条路线需要重新买票,给出K个人的位置,每个人都需要到达同一个点去,每个人有钱,有的还有月票(月票的话乘车不要钱~)问你到哪个点,总的花费最小,输出位置和最小花费。如果不能到达,输出0。
建图,每条路上任意两点的权为1,然后用floyd找从一个点到另一个点的最短路。然后枚举到达地点即可。
处理月票和是否连通需要注意下。
using namespace std;
const int MAX = 110;
typedef struct FFF{
int money,pos,tik;
}FFF;
FFF f[110];
int map[MAX][MAX];
int n,fnum,tpos;
int road[MAX],mincost;
void Floyd()
{
for(int i=1; i<=n; i++)
for(int k=1; k<=n; k++)
for(int j=1; j<=n; j++)
if( map[k][i] != INT_MAX && map[i][j] != INT_MAX
&& map[k][j] > map[k][i] + map[i][j] )
map[k][j] = map[k][i] + map[i][j];
}
int compute(int x)
{
int cost = 0;
for(int k=0; k<fnum; k++)
{
if( map[x][f[k].pos] == INT_MAX )
return -1;
if( !f[k].tik && map[x][f[k].pos] > f[k].money )
return -1;
if( !f[k].tik )
cost += map[x][f[k].pos];
}
return cost;
}
int solve()
{
for(int i=1; i<=n; i++)
{
int ans = compute(i);
if( ans != -1 && ans < mincost )
{
mincost = ans;
tpos = i;
}
}
return mincost;
}
int main()
{
int m,num;
scanf("%d %d",&n,&m);
for(int i=1; i<=n; i++)
{
for(int k=1; k<=n; k++)
map[i][k] = INT_MAX;
map[i][i] = 0;
}
while( m-- )
{
scanf("%d",&num);
for(int i=0; i<num; i++)
scanf("%d",&road[i]);
for(int i=0; i<num; i++)
for(int k=i+1; k<num; k++)
map[road[i]][road[k]] = map[road[k]][road[i]] = 4;
}
scanf("%d",&fnum);
for(int i=0; i<fnum; i++)
scanf("%d%d%d",&f[i].money,&f[i].pos,&f[i].tik);
Floyd();
mincost = INT_MAX;
int ans = solve();
if( ans == INT_MAX )
printf("0/n");
else
printf("%d %d/n",tpos,ans);
return 0;
}