题目要求必须按照L O V E 的顺序行走,且必须至少有一个完整的LOVE,说明可以经过同一个点多次
对每个点拆分为4个点,分别为从L,O,V,E到达。起始点看做是从E到达的
spfa时发现当前点距离相同,比较经过的边数,此时若边数更大,也要入队列!因为要更新后面的点经过的边数
trick 是点可以有自环,当N = 1时
1 4
1 1 1 L
1 1 1 O
1 1 1 V
1 1 1 E
还有就是数据可能会超int
敲了两遍,第一遍dijsktra怎么测都对,trick也都想到了,就是WA到死,第二遍初始化手贱4写成3。。。
附送好多组数据。。。都是自己编的
//#pragma comment(linker, "/STACK:102400000,102400000") //HEAD #include <cstdio> #include <cstring> #include <vector> #include <iostream> #include <algorithm> #include <queue> #include <string> #include <set> #include <stack> #include <map> #include <cmath> #include <cstdlib> using namespace std; //LOOP #define FE(i, a, b) for(int i = (a); i <= (b); ++i) #define FED(i, b, a) for(int i = (b); i>= (a); --i) #define REP(i, N) for(int i = 0; i < (N); ++i) #define CLR(A,value) memset(A,value,sizeof(A)) //STL #define PB push_back //INPUT #define RI(n) scanf("%d", &n) #define RII(n, m) scanf("%d%d", &n, &m) #define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k) #define RS(s) scanf("%s", s) typedef long long LL; const int MAXN = 1010; #define FF(i, a, b) for(int i = (a); i < (b); ++i) #define FD(i, b, a) for(int i = (b) - 1; i >= (a); --i) #define CPY(a, b) memcpy(a, b, sizeof(a)) #define FC(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++) #define EQ(a, b) (fabs((a) - (b)) <= 1e-10) #define ALL(c) (c).begin(), (c).end() #define SZ(V) (int)V.size() #define RIV(n, m, k, p) scanf("%d%d%d%d", &n, &m, &k, &p) #define RV(n, m, k, p, q) scanf("%d%d%d%d%d", &n, &m, &k, &p, &q) #define WI(n) printf("%d\n", n) #define WS(s) printf("%s\n", s) #define sqr(x) x * x typedef vector <int> VI; typedef unsigned long long ULL; const double eps = 1e-10; const LL MOD = 1e9 + 7; typedef long long LL; using namespace std; const int maxn = 3010; const LL INF = 1e18; struct Edge{ int from, to, dis, let; Edge(int u, int v, int w, int let): from(u), to(v), dis(w), let(let) {} }; struct Node{ int u, let; Node(int d, int let): u(d), let(let) {} }; int n, m; LL d[maxn][5]; int num[maxn][5], inq[maxn][5]; VI G[maxn]; vector<Edge> edges; void init(int nn) { n = nn; edges.clear(); FE(i, 0, n) G[i].clear(); } void addEdge(int u, int v, int w, int let) { edges.push_back(Edge(u, v, w, let)); m = edges.size(); G[u].push_back(m - 1); } void spfa() { queue<Node> Q; Q.push(Node(1, 3)); FE(i, 0, n) REP(j, 4) d[i][j] = INF; CLR(num, 0), CLR(inq, 0); d[1][3] = 0, inq[1][3] = 1; while (!Q.empty()) { Node x = Q.front(); Q.pop(); int u = x.u, let = x.let; inq[u][let] = 0; REP(i, G[u].size()) { Edge& e = edges[G[u][i]]; if (e.let != (let + 1) % 4) continue; if (d[e.to][e.let] > d[u][let] + e.dis || !d[e.to][e.let]) { d[e.to][e.let] = d[u][let] + e.dis; num[e.to][e.let] = num[u][let] + 1; // printf("now:%d to:%d letter:%d num:%d d:%d\n", u, e.to, e.let, num[e.to][e.let], d[e.to][e.let]); if (!inq[e.to][e.let]) { inq[e.to][e.let] = 1; Q.push(Node(e.to, e.let)); } } else if (d[e.to][e.let] == d[u][let] + e.dis && num[e.to][e.let] <= num[u][let]) { num[e.to][e.let] = num[u][let] + 1; if (!inq[e.to][e.let]) { inq[e.to][e.let] = 1; Q.push(Node(e.to, e.let)); } } } } } int main() { int T, N, M; RI(T); FE(kase, 1, T) { int x, y, z, let; char s[20]; RII(N, M); init(N); REP(i, M) { RIII(x, y, z); RS(s); if (s[0] == 'L') let = 0; if (s[0] == 'O') let = 1; if (s[0] == 'V') let = 2; if (s[0] == 'E') let = 3; addEdge(x, y, z, let); addEdge(y, x, z, let); } spfa(); printf("Case %d: ", kase); // cout << d[N][3] << num[N][3] << endl; if (d[N][3] == INF || num[N][3] / 4 < 1) { printf("Binbin you disappoint Sangsang again, damn it!\n"); continue; } printf("Cute Sangsang, Binbin will come with a donkey after travelling %I64d meters and finding %d LOVE strings at last.\n", d[N][3], num[N][3] / 4); } return 0; } /* 55 6 6 1 2 10 L 2 3 20 O 2 4 30 O 3 5 30 V 4 5 10 V 5 6 10 E 4 4 1 2 1 L 2 1 1 O 1 3 1 V 3 4 1 E 4 4 1 2 1 L 2 3 1 O 3 4 1 V 4 1 1 E 1 0 2 1 1 2 1 E 2 8 1 1 2 L 1 1 1 O 1 1 1 V 1 1 1 E 1 2 3 L 2 1 1 O 1 2 1 V 2 1 1 E 12 12 1 5 5 L 5 6 5 O 6 7 5 V 7 12 5 E 1 2 1 L 2 3 1 O 3 4 1 V 4 8 1 E 8 9 1 L 9 10 1 O 10 11 1 V 11 12 13 E 23 24 1 5 5 L 5 6 5 O 6 7 5 V 7 12 5 E 1 2 1 L 2 3 1 O 3 4 1 V 4 8 1 E 8 9 1 L 9 10 1 O 10 11 1 V 11 12 13 E 12 13 1 L 13 14 1 O 14 15 1 V 15 16 1 E 16 17 1 L 17 18 1 O 18 19 1 V 19 23 13 E 12 20 5 L 20 21 5 O 21 22 5 V 22 23 5 E */
hdu4360 spfa+拆点
时间: 2024-10-06 03:06:20