问题分析
基本算是裸的dijkstra了,但必须优化一下,这里蒻用的邻接表优化的。求出源点到其他顶点的最短路之后,再从中找出源点到其他顶点的相对最长路径,就是最后所有组件坏掉之前所经过的时间,从源点到其他顶点路径长度比这段路径短的顶点个数就是最后坏掉的组件。
#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cmath>
#include <vector>
#include <cstring>
#include <queue>
using namespace std;
const int N = 1e5+3, inf = 1e9+7;
int u[N],v[N],w[N],first[N],nxt[N],dis[N];
bool book[N];
int t,n,d,c;
void init()
{
memset(first,-1, sizeof(first));
memset(book,0, sizeof(book));
for(int i = 1; i <= n; ++i){
dis[i] = inf;
}
}
void solve()
{
for(int i = 1; i <= n-1; ++i){
int min = inf,u;
for(int j = 1; j <= n; ++j){
if(book[j]==0&&dis[j]<min){
min = dis[j];
u = j;
}
}
book[u] = 1;
for(int l = first[u]; l != -1; l = nxt[l]){
if(w[l]<inf){
if(dis[u] + w[l] < dis[v[l]])//松弛边
dis[v[l]] = dis[u]+w[l];
}
}
}
//找出单源最短路中的最长路径
int max1 = 0, cnt = 0;
for(int i = 1; i <= n; ++i){
if(max1<=dis[i]&&dis[i]!=inf){
max1 = dis[i];
}
}
//比最长路径短的顶点个数就是坏掉的组件个数
for(int i = 1; i <= n; ++i){
if(max1>=dis[i]){
cnt++;
}
}
printf("%d %d\n",cnt,max1);
}
int main()
{
//freopen("in.txt","r",stdin);
cin>>t;
while(t--)
{
scanf("%d%d%d",&n,&d,&c);
init();
for(int i = 1; i <= d; ++i){
scanf("%d%d%d",&v[i],&u[i],&w[i]);
nxt[i] = first[u[i]];
first[u[i]] = i;
if(u[i]==c)
dis[v[i]] = w[i];
}
book[c] = 1;
dis[c] = 0;
solve();
}
return 0;
}