炸学校
Time Limit: 2000ms Memory limit: 65536K 有疑问?点这里^_^
题目描述
“小儿么小二郎,背着那炸弹炸学校,不怕那太阳晒,也不怕那风雨狂。”估计这首歌我们大家都耳熟能详了。
于是就有一群小学生们商量着炸学校。要把本市的小学的都给炸掉。于是他们商量好了一个出发点source与集合点sink。然后有无数个小学生,n-2个学校,每个小学生都从出发点出发,负责背着一个炸弹,然后把炸弹偷偷放置在一个学校里,然后返回到集合点。
于是就有一群小学生们商量着炸学校。要把本市的小学的都给炸掉。于是他们商量好了一个出发点source与集合点sink。然后有无数个小学生,n-2个学校,每个小学生都从出发点出发,负责背着一个炸弹,然后把炸弹偷偷放置在一个学校里,然后返回到集合点。
由于这群小学生们还急着回去玩撸啊撸,所以他们想尽快把所有学校都炸完。这里有m条无向路,每条路都连接着u和v这两个学校,经过这条路的时间花费为t。这些小学生只能从这些路中经过。他们同时从出发点出发,他们想知道炸完所有学校并且都回到集合点的最少需要多长时间。
输入
第一行为一个整数T,表示T组测试数据。
第二行为整数n(3<=n<=1000),代表学校的数量(包括出发点和集合点),还有整数m(m<10^5),表示有多少条无向路。
然后接下来是m行,每一行的三个整数分别是u,v,t(0<=u,v, u!=v, 0<=t<=10^5)
然后给出两个整数source和sink,分别代表出发点和集合点。(0<=source,sink)。
输入数据保证可以炸毁所有学校,并且可以到达集合点。不保证没有重边。
输出:
输出
对于第x组数据输出一行“Case #x:”,然后是一个整数表示最少需要的时间。
示例输入
1 5 5 1 0 1 1 2 3 1 3 3 4 2 2 3 4 1 4 2
示例输出
Case #1: 9
提示
炸完所有学校的最短时间,即是最慢的那一个人炸完所用的时间,每个点求一次最短路,果断的TLE了,,,,其实两遍即可,然后记下到每个点的距离
#include <iostream>
#include <cstring>
#include <cstdio>
#include <string>
#include <stdlib.h>
#include <queue>
#include <algorithm>
using namespace std;
const int MAX = 999999;
int a[1010][1010];
int b[1010],v[1010];
int flag;
int v1[1010];
int v2[1010];
int n,m;
void Dijkstra(int s)
{
int k;
memset(b,0,sizeof(b));
for(int i=0; i<n; i++)
v[i]=a[s][i];
b[s]=1;
v[s]=0;
int min=0;
for(int i=0; i<n-1; i++)
{
min=MAX;
for(int j=0; j<n; j++)
{
if(!b[j]&& min > v[j])
{
min=v[j];
k=j;
}
}
if(min==MAX)
break;
b[k]=1;
for(int j=0; j<n; j++)
{
if(!b[j] && v[j] > v[k]+a[k][j])
{
v[j]=v[k]+a[k][j];
}
}
}
if(flag)
{
for(int i=0;i<n;i++)
v1[i]=v[i];
}
else
{
flag++;
for(int i=0;i<n;i++)
v2[i]=v[i];
}
}
int main()
{
int T;
scanf("%d",&T);
for(int r=1; r<=T; r++)
{
flag=0;
memset(a,MAX,sizeof(a));
for(int i=0;i<n;i++)
a[i][i]=0;
scanf("%d%d",&n,&m);
for(int i=0; i<m; i++)
{
int u,v,w;
scanf("%d%d%d",&u,&v,&w);
if(w<a[u][v])
{
a[u][v]=w;
a[v][u]=w;
}
}
int s,e;
scanf("%d%d",&s,&e);
Dijkstra(s);
Dijkstra(e);
int ans=-1;
for(int i=0;i<n;i++)
{
if(ans<v1[i]+v2[i])
ans=v1[i]+v2[i];
}
printf("Case #%d: %d\n",r,ans);
}
return 0;
}