这题还是再考最短路算法,在这里还是迪杰斯特拉。
但难点在于建图,在这里将同一种种类的传送门具化成一个点,拥有这个传送门的可以通过这个传送门进行到达。但在花费上是二倍。
还有就是不要使用map<pair<int,int>,int>来保存边。这个数据类型操作会导致这道题超时。。。。。。
//要移动到同一点 //每个点上有一些传送门 //计算1到每个点的最短路和n到每个点的最短路。然后遍历每个点将两个最短路相加求最小的结果 //那么问题就是如何计算最短路。 //每个点都有附属的一些传送门。计算传送门之间的最短路然后让每个点来认领就行。 //什么狗屁附属,不同的传送门其实就是不同点之间的连线,但这连线也会产生重复的,重复的去取最短的那一个即可。 #include <bits/stdc++.h> using namespace std; #define int long long const int maxn = 2000010; struct sy{ int to; int next; int w; } edge[2000010]; int head[2000010]; struct Node{ int number; int len; bool operator < (const Node& n) const { return len>n.len; } }; priority_queue<Node> pq; int n, m; int cnt = 0; int vis[maxn]; void add_edge(int x, int y, int w) { edge[++cnt].next = head[x]; edge[cnt].to = y; edge[cnt].w = w; head[x] = cnt; } void Dijkstra(int bg, int ans[]) { memset(vis, 0, sizeof(vis)); memset(ans, 127, sizeof(vis)); pq.push({bg, 0}); ans[bg] = 0; while (pq.size()) { int number = pq.top().number; pq.pop(); // cout<<"number="<<number<<" head[number]="<<ans[number]<<endl; if (vis[number]) continue; vis[number] = true; for (int i=head[number];i;i = edge[i].next) { int next = edge[i].to; int w = edge[i].w; // cout<<"next="<<next<<endl; // cout<<ans[number]+w<<" "<<ans[next]<<endl; if (ans[number]+w<ans[next]) { ans[next] = ans[number]+w; pq.push({next, ans[next]}); } } } } signed main() { cin>>n>>m; for (int i=1;i<=m;i++) { int t, s, x; cin>>t>>s; for (int j=1;j<=s;j++) { cin>>x; add_edge(i+100000, x, t); add_edge(x, i+100000, t); } } //接着使用迪杰斯特拉算法求最短路 int ans_one[maxn]; int ans_n[maxn]; Dijkstra(1, ans_one); Dijkstra(n, ans_n); int ans = INT_MAX; //遍历所有的点 for (int i=1;i<=n;i++) { // cout<<ans_one[i]<<' '<<ans_n[i]<<endl; ans = min(ans, max(ans_one[i],ans_n[i])); } vector<int> vt; //找点 for (int i=1;i<=n;i++) { if (max(ans_one[i],ans_n[i])==ans) vt.push_back(i); } if (ans>=2139062143) { cout<<-1<<endl; return 0; } cout<<ans/2<<endl; vector<int>::iterator vit; for (vit = vt.begin();vit!=vt.end();vit++) { cout<<(*vit)<<' '; } return 0; }