在一个名叫刀塔的国家里,有一只猛犸正在到处跑着,希望能够用它的长角抛物技能来撞飞别人。已知刀塔国有 N 座城市,城市之间由 M 条道路互相连接,为了拦住这头猛犸,每条道路上设置了 Vi 人的团队。
这只猛犸从 S 号城市出发,它可以选择:
猛犸经过一条道路后,就会把路上的人全部撞飞。作为一头爱喝雪碧的仁慈的猛犸,自然希望尽可能的少撞飞人。请你帮忙计算一下在最优的选择下,最少需要撞飞多少人才能够到达目标城市?
输入第一行是四个正整数 N,M,S,T (2≤N≤500,1≤M≤105),表示有 N 个城市,M 条道路,猛犸从 S 号城市出发,可以选择到达 T 号城市。
接下来的 M 行,每行三个正整数 Xi,Yi,Vi (0≤Vi≤100),表示从 Xi 号城市到 Yi 号城市有一条道路,道路上有 Vi 人的团队。道路可双向通行,城市编号从 1 开始,两个城市之间最多只有一条道路,且没有一条道路连接相同的城市。
数据保证两种选择里至少有一种是可行的。
输出两行,第一行是两个数字,分别对应上面的两种选择分别最少需要撞飞多少人。如果无论撞飞多少人都无法满足选择要求,则输出 -1
。
第二行是一个句子,如果第一种(回到原点)的选择比较好,就输出 Win!
,否则输出Lose!
。
- 5 6 1 5
- 1 2 1
- 2 3 2
- 3 4 3
- 4 1 5
- 3 5 4
- 4 5 1
在这里给出相应的输出。例如:
- 11 6
- Lose!
题意: 有n个点m条边,起点s和终点t,现在猛犸有两种行动路径,一种是从s走到t,一种是从s出发转一圈再回到s,两种行动都不允许重复经过同一条边,问各自最短路是多少。
分析: 对于从s到t的最短路很简单,就是套一个dijkstra板子,对于从s出去再绕一圈回来的情况,其实就相当于从s的某个相邻节点i出发,并且删掉i到s的那条边的情况下从i走到s的最短路,再加上i到s的边权就是这一圈下来从i出发的最短路了,猛犸可能从s的各个相邻点出发,所以需要每个相邻点都处理一遍,也就是跑最多n-1次dijkstra,取一个最小值就是绕圈下的最短路了,时间复杂度为O(n*m*logn),如果不使用堆优化的dijkstra可能会更快。
具体代码如下:
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #include
- #define inf 0x3f3f3f3f
- #define pii pair
- using namespace std;
-
- int n, m, s, t, mn;
- vector
g[505]; - bool vis[505];
- int dis[505];
-
- void dijkstra(int s, int type){
- priority_queue
, greater >q; - dis[s] = 0;
- q.push(make_pair(dis[s], s));
- while(q.size()){
- int now = q.top().second;
- q.pop();
- if(vis[now]) continue;
- vis[now] = true;
- for(int i = 0; i < g[now].size(); i++){
- int to = g[now][i].second, w = g[now][i].first;
- if(type == 1 && now == s && to == ::s) continue;//禁用某条边
- if(dis[to] > dis[now]+w){
- dis[to] = dis[now]+w;
- q.push(make_pair(dis[to], to));
- }
- }
- }
- }
-
- signed main()
- {
- ios::sync_with_stdio(0);
- cin.tie(0);
- cin >> n >> m >> s >> t;
- for(int i = 1; i <= n; i++){
- dis[i] = inf;
- vis[i] = false;
- }
- for(int i = 1; i <= m; i++){
- int u, v, w;
- cin >> u >> v >> w;
- g[u].push_back(make_pair(w, v));
- g[v].push_back(make_pair(w, u));
- }
- dijkstra(s, 0);
- int temp = dis[t];
- int mn = inf;
- for(int i = 0; i < g[s].size(); i++){
- int to = g[s][i].second, w = g[s][i].first;
- for(int j = 1; j <= n; j++){
- vis[j] = false;
- dis[j] = inf;
- }
- dijkstra(to, 1);
- mn = min(mn, dis[s]+w);
- }
- if(mn != inf) cout << mn << " ";
- else cout << "-1 ";
- if(temp != inf) cout << temp;
- else cout << "-1";
- cout << endl;
- if(mn < temp) cout << "Win!";
- else cout << "Lose!";
- return 0;
- }