Description
Input
Output
题目大意:有一个软件,要从1升级到n。每个升级有一个花费,用了P之后就不能再用L,求最小花费。
思路:正解是DP?不管。我们用最短路。建双层图,对于a→b L,在第一层建一条边。对于a→b P,从第一层的a建一条边到第二层的b,再从第二层的a建一条边到第二层的b。对于a→b C,第一层建一条边,第二层建一条边。再从第一层的n建一条边到第二层的n,费用为0。那么就保证了走过了P之后不会再走L,用SPFA求个最短路圆满解决。个人认为比D好写多了。我们要把图论发扬光大O(∩_∩)O~
代码(31MS):
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #include <algorithm> 5 #include <queue> 6 using namespace std; 7 typedef long long LL; 8 9 const int MAXN = 20010; 10 const int MAXE = MAXN * 2; 11 12 int head[MAXN]; 13 int to[MAXE], next[MAXE], cost[MAXE]; 14 int n, m, st, ed, ecnt; 15 16 void init() { 17 memset(head, 0, sizeof(head)); 18 ecnt = 1; 19 } 20 21 void add_edge(int u, int v, int c) { 22 to[ecnt] = v; cost[ecnt] = c; next[ecnt] = head[u]; head[u] = ecnt++; 23 //printf("%d->%d %d\n", u, v, c); 24 } 25 26 char s[22]; 27 28 void input() { 29 scanf("%d%d", &n, &m); 30 int a, b, c; 31 for(int i = 0; i < m; ++i) { 32 scanf("%d%d%d%s", &a, &b, &c, s); 33 if(*s == 'P') { 34 add_edge(a, b + n, c); 35 add_edge(a + n, b + n, c); 36 } 37 if(*s == 'L') { 38 add_edge(a, b, c); 39 } 40 if(*s == 'C') { 41 add_edge(a, b, c); 42 add_edge(a + n, b + n, c); 43 } 44 } 45 add_edge(n, n + n, 0); 46 st = 1, ed = 2 * n; 47 } 48 49 LL dis[MAXN]; 50 bool vis[MAXN]; 51 52 void SPFA() { 53 memset(dis, 255, sizeof(dis)); 54 memset(vis, 0, sizeof(vis)); 55 queue<int> que; que.push(st); 56 dis[st] = 0; 57 while(!que.empty()) { 58 int u = que.front(); que.pop(); 59 vis[u] = false; 60 for(int p = head[u]; p; p = next[p]) { 61 int &v = to[p]; 62 if(dis[v] == -1 || dis[v] > dis[u] + cost[p]) { 63 dis[v] = dis[u] + cost[p]; 64 if(!vis[v]) que.push(v); 65 vis[v] = true; 66 } 67 } 68 } 69 } 70 71 void output() { 72 if(dis[ed] == -1) puts("Offline"); 73 else { 74 puts("Online"); 75 cout<<dis[ed]<<endl; 76 } 77 } 78 79 int main() { 80 init(); 81 input(); 82 SPFA(); 83 output(); 84 }