題目:旅旅旅遊
題解:分別求出以1爲起點的最短距離,和以n爲起點的最短距離。然後對每條邊進行判斷,判斷這條邊是否爲最短路徑的邊。最後再把剩下的邊判斷一下就好了。
#include <bits/stdc++.h>
#include <cstdlib>
using namespace std;
typedef long long ll;
typedef pair<ll,int>P;
const int N = 5e5+10;
const ll mod = 1e9+7;
const ll inf = 10000000000000000;
int random(int n){
return (ll)rand()*rand()%n;
}
struct str{
int v;
ll s;
int next;
}e[N<<5];
int head[N<<5],cnt;
int n,m;
map<P,ll>vis;
int vv[N];
void add(int x,int y,ll z){
e[++cnt].v = y;
e[cnt].s = z;
e[cnt].next = head[x];
head[x] = cnt;
}
void Dijkstra(int s,ll dis[]){
memset(vv,0,sizeof vv);
priority_queue<P,vector<P>,greater<P> >que;
que.push(P(0,s));
dis[s] = 0;
while(!que.empty()){
P t = que.top();
que.pop();
if(vv[t.second]) continue;
vv[t.second] = 1;
for(int i = head[t.second];i;i = e[i].next){
int v = e[i].v;
ll s = e[i].s;
if(s+t.first < dis[v]){
dis[v] = s+t.first;
que.push(P(dis[v],v));
}
}
}
}
ll dis1[N],dis2[N];
int a[N],b[N];
ll c[N];
int Find(int x){
if(vv[x] == 0) return x;
else return vv[x] = Find(vv[x]);
}
bool check(){
int fa = Find(1);
for(int i = 1;i <= n;i++){
if(fa != Find(i)) return false;
}
return true;
}
int main(){
scanf("%d%d",&n,&m);
for(int i = 1;i <= m;i++){
int x,y;
ll z;
scanf("%d%d%lld",&x,&y,&z);
a[i] = x;b[i] = y;c[i] = z;
add(x,y,z);
add(y,x,z);
}
for(int i = 1;i <= n;i++){
dis1[i] = dis2[i] = inf;
}
Dijkstra(1,dis1);
Dijkstra(n,dis2);
memset(vv,0,sizeof vv);
for(int i = 1;i <= m;i++){
int u = a[i],v = b[i];
if(dis1[u]+dis2[v]+c[i] == dis1[n] || dis1[v]+dis2[u]+c[i] == dis1[n]){
continue;
}
u = Find(u);
v = Find(v);
if(u != v){
if(u > v) swap(u,v);
vv[u] = v;
}
}
if(check()){
printf("YES\n");
}else {
printf("NO\n");
}
return 0;
}
/*
6 9
1 2 1
1 3 1
2 3 3
2 4 1
3 5 4
3 6 3
4 5 1
5 6 1
2 5 2
*/