一个含有n个结点m条边的无向有权图,判断每个结点是否在从1到n的最短路径上
输入描述
第一行输入一个整数TTT,代表有TTT组测试数据 对于每一组测试数据,第一行有2个整数n,m,接下来mmm行每行有333个整数xi,yi,wi,表示x和y之间有一条权值为wi的边
输出描述
对于每组测试数据,在一行中输出n个整数,第i个整数代表iii号结点的关键性
样例输入:
2
6 7
1 2 1
2 3 1
2 4 1
2 5 2
3 5 1
4 5 2
5 6 1
4 6
1 2 1
1 3 1
1 4 2
2 3 1
2 4 1
3 4 1
样例输出
1 1 2 0 1 1
1 2 2 1
做题思路:先通过两次Dijkstra,把不在最短路上的点标价为0,再收集最短路上的边建成一个新图,通过tarjin找到割点。
#include<bits/stdc++.h>
using namespace std;
typedef long long LL;
const int mod = 1e9 + 7;
const int maxn = 1e6 + 1;
const int inf = 0x3f3f3f3f;
const double Pi = acos(-1.0);
const LL INF = 0x3f3f3f3f3f3f3f3f;
template<class T, class F> inline void mem(T a,F b, int c) {for(int i=0;i<=c;++i)a[i]=b;}
template<class T> inline void read(T &x,T xk=10) { // xk 为进制
char ch = getchar(); T f = 1, t = 0.1;
for(x=0; ch>'9'||ch<'0'; ch=getchar()) if(ch=='-')f=-1;
for(;ch<='9'&&ch>='0';ch=getchar())x=x*xk+ch-'0';if(ch=='.')
for(ch=getchar();ch<='9'&&ch>='0';ch=getchar(),t*=0.1)x+=t*(ch-'0');x*=f;
}
struct edge {
int to, next, w; edge(){}
edge(int to, int next, int w): to(to), next(next), w(w){}
}e[maxn]; int head[maxn], tot, Head[maxn], res[maxn]; bool visit[maxn];
struct node {
LL x, w;
node(LL x, LL w): x(x), w(w){}
bool operator< (const node &n1) const {
return w > n1.w;
}
};
LL dis1[maxn], disn[maxn];
void dijkstra(int root, LL *dis) {
dis[root] = 0;
priority_queue<node> q;
q.push(node(root, dis[root]));
while(!q.empty()) {
node temp = q.top();
q.pop();
int x = temp.x;
visit[x] = true;
for(int i = head[x]; ~i; i = e[i].next) {
int j = e[i].to, w = e[i].w;
if (visit[j]) continue;
if (dis[j] > dis[x] + w) {
dis[j] = dis[x] + w;
q.push(node(j, dis[j]));
}
}
}
}
int dfn[maxn], low[maxn], Index;
void tarjan(int x) {
dfn[x] = low[x] = ++ Index;
for(int i = Head[x]; ~i; i = e[i].next) {
int j = e[i].to;
if (!dfn[j]) {
tarjan(j);
low[x] = min(low[x], low[j]);
if (low[j] >= dfn[x]) res[x] = 1;
}
else {
low[x] = min(low[x], dfn[j]);
}
}
}
int main() {
int T; read(T);
while(T --) {
tot = 0; Index = 0;
int n, m; read(n), read(m);
mem(head, -1, n);
mem(Head, -1, n);
for(int i = 1; i <= m; ++ i) {
int u, v, w; read(u), read(v), read(w);
e[++tot] = edge(v, head[u], w), head[u] = tot;
e[++tot] = edge(u, head[v], w), head[v] = tot;
}
mem(visit, 0, n); mem(dis1, INF, n); dijkstra(1, dis1);
mem(visit, 0, n); mem(disn, INF, n); dijkstra(n, disn);
mem(visit, 0, n);
for(int i = 1; i <= n; ++ i) {
if (dis1[i] + disn[i] == dis1[n]) res[i] = 2;
else res[i] = 0;
visit[i] = true;
for(int j = head[i]; ~j; j = e[j].next) {
int k = e[j].to, w = e[j].w;
if(dis1[i] + disn[k] + w == dis1[n]) {
e[++tot] = edge(k, Head[i], w), Head[i] = tot;
e[++tot] = edge(i, Head[k], w), Head[k] = tot;
}
}
}
mem(dfn, 0, n);
tarjan(1);
for(int i = 1; i < n; ++ i) {
printf("%d ", res[i]);
}
printf("1\n");
}
return 0;
}